async/await
和承诺密切相关。async
函数返回 Promise,await 是等待 Promise 得到解决的语法糖。
混合承诺和承诺的唯一缺点async
函数可能会影响代码的可读性和可维护性,但是您当然可以使用异步函数的返回值作为 Promise 以及await
对于返回承诺的常规函数。
您是否选择其中之一主要取决于可用性(您的node.js/浏览器是否支持async
?)以及您的审美偏好,但一个好的经验法则(基于我在撰写本文时自己的偏好)可能是:
如果您需要串行运行异步代码:请考虑使用async/await
:
return asyncFunction()
.then(result => f1(result))
.then(result2 => f2(result2));
vs
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result2);
如果您需要嵌套承诺:使用async/await
:
return asyncFunction()
.then(result => {
return f1(result)
.then(result2 => f2(result, result2);
})
vs
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result, result2);
如果您需要并行运行它:使用 Promise。
return Promise.all(arrayOfIDs.map(id => asyncFn(id)))
建议您可以使用await
在表达式中等待多个任务,如下所示:
*注意,这仍然按从左到右的顺序等待,如果您不希望出现错误,那么这是可以的。否则,行为会有所不同,因为快速失败行为 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all#Promise.all_fail-fast_behaviour of Promise.all()
const [r1, r2, r3] = [await task1, await task2, await task3];
(async function() {
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Create Promises');
const task1 = t1(100);
const task2 = t1(200);
const task3 = t1(10);
console.log('Await for each task');
const [r1, r2, r3] = [await task1, await task2, await task3];
console.log('Done');
}())
但正如Promise.all
,如果出现错误,并行 Promise 需要得到正确处理。您可以阅读更多相关内容here https://stackoverflow.com/a/53345172/985454.
请注意不要将前面的代码与以下代码混淆:
let [r1, r2] = [await t1(100), await t2(200)];
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Promise');
Promise.all([t1(100), t1(200), t1(10)]).then(async() => {
console.log('Await');
let [r1, r2, r3] = [await t1(100), await t1(200), await t1(10)]
});
使用这两种方法并不等效。了解更多关于差异的信息 https://stackoverflow.com/a/54291660/428486.
到底,Promise.all
是一种更简洁的方法,可以更好地扩展到任意数量的任务。