JavaScript ES7 async/await
JavaScript中的异步编程解决方案一直在发展,从ES5的Callback
到ES6的Promise
、Generator
,再到ES7的async
/await
。对于开发人员越来越友好、直观,写法越来越符合人们的直觉。
async/await
Node.js 7.6以上版本才支持async/await。
async/await的目的是在Promise的基础上进一步简化异步的同步调用。
调用async函数时会返回一个Promise对象。当这个async函数返回一个值时,Promise的resolve方法会负责传递这个值;当async函数抛出异常时,Promise的reject方法也会传递这个异常值。
await“等待”的是一个Promise对象或其他任意value。如果await后面跟的不是一个Promise,它被转化为Promise.resolve(value)。
await只能在async内部使用。
例子
例子1
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
function add1(x) {
var a = await resolveAfter2Seconds(20);
return a;
}
/* 因为await没有在async内部使用,运行时会报错:
var a = await resolveAfter2Seconds(20);
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Unexpected identifier
*/
例子2
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function add1(x) {
var a = resolveAfter2Seconds(20);
var b = resolveAfter2Seconds(30);
return x + await a + await b;
}
add1(10).then(v => {
console.log(v); // 2秒后打印60
});
async function add2(x) {
var a = await resolveAfter2Seconds(20);
var b = await resolveAfter2Seconds(30);
return x + a + b;
}
add2(10).then(v => {
console.log(v); // 4秒后打印60
});
/*
注意以上打印结果的时间,await的串行和并行执行,await的位置不同,执行的顺序也不一样。
*/
异常处理
用try catch捕获async/await的异常:
try {
await f();
}
catch (err) {
// 静态函数Promise.reject会走到这里
// async代码异常,也会走这里
}
最佳实践
将基本的业务逻辑封装为一个个Promise
,然后使用async/await对Promises进行组合调用。
async/await的与Generator的联系与区别
async函数就是Generator函数的语法糖。
async函数就是将Generator函数的星号(*)替换成async,将yield替换成await,仅此而已。
如何在for循环中使用async/await
使用for of代替forEach。
参考:https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await