前几天面试,面试官提问了一个我之前没有考虑过的问题: Q: 比如有一个场景,用async/await来处理异步逻辑,但是async/await是等一个执行完后才执行下一个,怎么提高效率让多个异步逻辑并发执行。
说实话,当时听到有点懵,之前就是用await等待异步处理完然后获取结果进行操作,简单来说就是只触发一次异步操作而且没有考虑过并发的场景,而面试官后面还引导了我一下,说promise中是怎么实现多个异步请求并发操作的,我说应该是用Promise.all,面试官是得,那async/await是比promise还要新的解决方案,总不会开倒车吧,其实应该提示的差不多了,而且我也想说一下promise.all的原理,然后套用到await上,但是最终还是没有信心,面试官也没有太追着问。
这个问题的场景毕竟还是很多的,所以我觉得有必要了解一下,但是网上搜索出来的大多还是如何使用async/await,于是我想起了阮一峰大神的写的es6入门,果然让我找到了答案。
点击查看原文
let foo = await getFoo();
let bar = await getBar();
async函数内部执行是一种继发关系,就是逐个执行,但是多个await函数之间不存在这种关系的话,并发执行无疑能将效率大大增加,所以我们可以改变一下写法:
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
//写法三
[getFoo, getBar].forEach(async item=> await item())
getFoo和getBar是两个没有关系的异步函数,
第一种方法借助Promise.all这个方法来实现,把他们传入Promise.all来并发执行并且等待所有的thenable函数(await后必须跟的是这样一个函数,也就是具有then方法的对象)执行完毕。
另外
Promise.all的行为是:A,B,C都resolve,则resolve, 只要有一个reject, 则reject,这明显不是我们需要的。
我们需要的是,不论A,B,C哪个reject,Promise.all依旧resolve,
所以需要将[A(), B(), C()]这个可能包含rejected promise的promise数组通过map方法映射一组新的promise数组,这个新的promise数组中promise都是resolve的
所以需要的可以这么写
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => Promise.resolve(db.post(db)));
let results = await Promise.all(promises);
console.log(results);
}