基本用法
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
下面是另一个例子,指定多少毫秒后输出一个值。
|
|
上面代码指定50毫秒以后,输出hello world。
由于async函数返回的是 Promise 对象,可以作为await命令的参数。所以,上面的例子也可以写成下面的形式。
|
|
返回 Promise 对象
async函数返回一个Promise
对象。
async函数内部return
语句返回的值,会成为then
方法回调函数的参数。
|
|
上面代码中,函数f内部return命令返回的值,会被then方法回调函数接收到。
async函数内部抛出错误,会导致返回的 Promise
对象变为reject
状态。抛出的错误对象会被catch
方法回调函数接收到。
|
|
Promise 对象的状态变化
async函数返回的 Promise
对象,必须等到内部所有await
命令后面的 Promise
对象执行完,才会发生状态改变,除非遇到return
语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then
方法指定的回调函数。
下面是一个例子。
上面代码中,函数getTitle内部有三个操作:抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成,才会执行then方法里面的console.log。
await命令
正常情况下,await
命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve
的 Promise 对象。
|
|
上面代码中,await命令的参数是数值123,它被转成 Promise 对象,并立即resolve。
await命令后面的 Promise 对象如果变为reject
状态,则reject的参数会被catch
方法的回调函数接收到。
注意,上面代码中,await
语句前面没有return
,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的。
只要一个
await
语句后面的Promise
变为reject
,那么整个async
函数都会中断执行。
|
|
上面代码中,第二个await语句是不会执行的,因为第一个await语句状态变成了reject。
有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await放在try…catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
|
|
另一种方法是await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误。
错误处理
如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。
防止出错的方法,也是将其放在try...catch
代码块之中。
如果有多个await
命令,可以统一放在try...catch
结构中。
|
|
使用注意点
await
命令后面的Promise
对象,运行结果可能是rejected
,所以最好把await
命令放在try...catch
代码块中,或者直接catch
。
|
|
- 多个
await
命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
|
|
上面代码中,getFoo和getBar是两个独立的异步操作(即互不依赖),被写成继发关系。这样比较耗时,因为只有getFoo完成以后,才会执行getBar,完全可以让它们同时触发。
|
|
|
|
上面两种写法,getFoo和getBar都是同时触发,这样就会缩短程序的执行时间。