Async Await 大法虽好,可是很多人忽略了一点!

async / await 对于异步的js是个好东西,尤其是在编写复杂的异步逻辑代码能明显的体现它的好处,与此同时在性能上也可以稍微优化。

在最新的ES7(ES2017)中提出的前端异步特性:async/await,配合Promise能使得我们在编写异步代码时变得像同步的方式,这样做不仅可以帮助我们的代码提高可阅读性,也更利于我们代码的后期维护。

最近业余时间给某公司做了个抽奖的小项目,具体不表。其中有一个操作是一次生成1000个小程序码,生成二维码是必须在客户端调用一个异步接口。用普通的Promise确实不好写,用async/await 大法就很自然了。

以下是伪代码

  let createQrImage = async ()=>{
    for(let i = 0; i<1000; i++) {
      await promiseCreateOneQr()
    }
  }

  createQrImage()

因为生成小程序码只能在客户端完成,所以需要在小程序里挂着执行函数。每调用一次小程序码的耗时大约是1-2秒,所以整个生成过程要持续将近30分钟。

这个未免太久了,毕竟这需要挂机进行。(额外提一下:按理来说我没有必要去给别人的产品优化,这只是个人的追求。我希望我的作品除了完成客户的基本要求外还有我个人的额外高要求)

所以要思考这个操作能否有优化空间,这也是常常使用async/await时忽略的一个:虽然它简化了代码的逻辑,但因为没使用到Promise的一个为并行任务而生的API--Promise.all,还有不少的优化空间。

于是改成以下伪代码:

  let createQrImage = async ()=>{
    for(let i = 0; i<100; i++) {
      await Promise.all(Array.from(new Array(10)).map(promiseCreateOneQr))
    }
  }

  createQrImage()

这段代码就是利用Promise.all这个API,每一次同时发起10个请求(这也是小程序支持的最大同时请求数),这样的优化结果是,每一次Promise.all十个请求的耗时大约是4-5秒左右。整个1000个小程序码的生成时间缩短到6-7分钟,仅是原先的1/4不到,极大的优化了产品的体验!

在客户本来对老的代码没有任何异议后,我依然做完这个优化,客户给我一个大大的赞!