含义
Generator 函数的语法糖,由多个异步操作包装成的一个 Promise 对象,await 命令就是内部 then 命令的语法糖。
用法
async 函数返回一个 Promise 对象,可使用 then 方法添加回调函数,函数执行时,一旦遇到 await 会等待异步操作返回结果,再执行后面的语句。
async function getStockPriceName(name) {
var symbol = await getStockSymbol(name);
var stockPrice = awati getStockPrice(symbol);
return stockPrice;
}
getStockPriceName('goog').then((res) => {
console.log(res);
})
语法
返回 Promise 对象
async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。
async function f() {
return 'hello world';
}
f().then(value => {
console.log(value); // hello world
})
async 函数内部抛出的错误会导致返回的 Promise 对象变为 reject 状态,错误对象会被 catch 方法回调函数接收到。
async function f() {
throw new Error('出错了');
}
f().then(
v => console.log(v),
e => console.log(e)
)
// 出错了
Promise 对象的状态变化
只有 async 方法内部的异步操作执行完才会执行 then 方法指定的回调函数。
await 语法
一般情况下,await 命令后是一个 Promise 对象,只要一个 await 语句后的 Promise 变为 reject,那么整个 asycn 函数都会中断执行。
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
错误处理
// 写法一
async function f() {
try {
var val1 = await step1();
var val2 = await step2();
var val3 = await step3();
} catch(e) {
console.log(e)
}
}
// 写法二
async function f() {
await somethingPromise()
.catch(e => {
cosole.log(e);
})
}
使用注意
如果多个 await 不存在继发关系,最好让它们同时触发。
// foo和bar是两个独立的异步操作,被写成继发关系比较费时,可以让它们同时触发。
let foo = await foo();
let bar = await bar();
// 写法一
let [foor, bar] = await Promise.all([foo(), bar()]);
// 写法二
let fooPromise = foo();
let barPromise = bar();
let foo = await fooPromise;
let bar = await barPromise;
await 命令只能用在 async 函数中,用在普通函数中会出错。
async function f() {
let docs = [{}, {}, {}];
docs.forEach((doc) => {
await db.post(doc); // 错误
})
}
与其他异步处理方法的比较
Promise 写起来 API(then, catch)过多,不够语义化。async 函数的实现最简洁,最符合语义,几乎没有不相关的代码。