ES6再理解———async/await的并发调用

5,882 阅读2分钟

前几天面试,面试官提问了一个我之前没有考虑过的问题: 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);
}