资讯专栏INFORMATION COLUMN

精读《用 Reduce 实现 Promise 串行执行》

JinB / 2989人阅读

摘要:引言本周精读的文章是,讲了如何利用实现串行执行。总结串行队列一般情况下用的不多,因为串行会阻塞,而用户交互往往是并行的。更多讨论讨论地址是精读用实现串行执行如果你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。

1 引言

本周精读的文章是 why-using-reduce-to-sequentially-resolve-promises-works,讲了如何利用 reduce 实现 Promise 串行执行。

在 async/await 以前 Promise 串行执行还是比较麻烦的,希望根据这篇文章可以理清楚串行 Promise 的思维脉络。

2 概述

除了依赖 async promise-fun 等工具库,最常用的队列操作就是 Array.prototype.reduce() 了:

let result = [1, 2, 5].reduce((accumulator, item) => {
  return accumulator + item;
}, 0); // <-- Our initial value.

console.log(result); // 8

最后一个值 0 是起始值,每次 reduce 返回的值都会作为下次 reduce 回调函数的第一个参数,直到队列循环完毕,因此可以进行累加计算。

那么将 reduce 的特性用在 Promise 试试:

function runPromiseByQueue(myPromises) {
  myPromises.reduce(
    (previousPromise, nextPromise) => previousPromise.then(() => nextPromise()),
    Promise.resolve()
  );
}

当上一个 Promise 开始执行(previousPromise.then),当其执行完毕后再调用下一个 Promise,并作为一个新 Promise 返回,下次迭代就会继续这个循环。

const createPromise = (time, id) => () =>
  new Promise(solve =>
    setTimeout(() => {
      console.log("promise", id);
      solve();
    }, time)
  );

runPromiseByQueue([
  createPromise(3000, 1),
  createPromise(2000, 2),
  createPromise(1000, 3)
]);

得到的输出是:

promise 1
promise 2
promise 3
3 精读

Reduce 是同步执行的,在一个事件循环就会完成(更多请参考 精读《Javascript 事件循环与异步》),但这仅仅是在内存快速构造了 Promise 执行队列,展开如下:

new Promise((resolve, reject) => {
  // Promise #1

  resolve();
})
  .then(result => {
    // Promise #2

    return result;
  })
  .then(result => {
    // Promise #3

    return result;
  }); // ... and so on!

Reduce 的作用就是在内存中生成这个队列,而不需要把这个冗余的队列写在代码里!

更简单的方法

感谢 eos3tion 同学补充,在 async/await 的支持下,runPromiseByQueue 函数可以更为简化:

async function runPromiseByQueue(myPromises) {
  for (let value of myPromises) {
    await value();
  }
}

多亏了 async/await,代码看起来如此简洁明了。

不过要注意,这个思路与 reduce 思路不同之处在于,利用 reduce 的函数整体是个同步函数,自己先执行完毕构造 Promise 队列,然后在内存异步执行;而利用 async/await 的函数是利用将自己改造为一个异步函数,等待每一个 Promise 执行完毕。

更多 Promise 拓展

天猪 同学分享的 promise-fun 除了串行 Promise 解决方案,还提供了一系列 Promise 功能拓展(有一些逐渐被 ES 标准采纳,比如 finally 已经进入 Stage 4),如果你的项目还无法使用 async/await,是不需要自己重新写一遍的,当然本文的原理还是需要好好理解。

Stage 相关可以进行拓展阅读 精读《TC39 与 ECMAScript 提案》。
4 总结

Promise 串行队列一般情况下用的不多,因为串行会阻塞,而用户交互往往是并行的。那么对于并行发请求,前端按串行顺序接收 Response 也是一个有意思的话题,留给大家思考。

5 更多讨论
讨论地址是:精读《用 Reduce 实现 Promise 串行执行》 · Issue #109 · dt-fe/weekly

如果你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98799.html

相关文章

  • 每周分享第 1 期

    摘要:由于微信不能访问外链,需要点击页尾左下角的阅读原文,才能访问本文中的链接。接下来让我带你走进高级前端的世界,在进阶的路上,共勉如果你想加群讨论每期面试知识点,公众号回复加群即可 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导)showImg(https://segmentfault.com/img/remote/1460000...

    Carbs 评论0 收藏0
  • 深入理解Webpack核心模块Tapable钩子[异步版]

    摘要:接上一篇文章深入理解核心模块钩子同步版中三个注册方法同步注册的是中对三个触发方法这一章节我们将分别实现异步的版本和版本异步钩子的版本的版本的版本异步的钩子分为并行和串行的钩子,并行是指等待所有并发的异步事件执行之后再执行最终的异步回调。 接上一篇文章 深入理解Webpack核心模块WTApable钩子(同步版) tapable中三个注册方法 1 tap(同步) 2 tapAsync(...

    AlphaWallet 评论0 收藏0
  • JavaScript 并行和串行任务/流程控制 的实现

    摘要:并行和串行任务在里面异步是一个很重要的知识点的异步跟其他语言不一样他是根据执行回调的方式来实现的。在之前,执行任务想要实现这个流程控制只能通过依赖来实现或者通过而在之后官方自己实现了和来实现。 JavaScript 并行和串行任务 在 JavaScript 里面 异步 是一个很重要的知识点,JS 的异步跟其他语言不一样, 他是根据执行回调的方式来 实现的。由于我们不知道异步什么时候会...

    bladefury 评论0 收藏0
  • 行星工单系统部分实现(1)-流程控制

    摘要:为使客服同学有序协同处理客户问题客服技术团队打造了多渠道整合的,可灵活配置的,便于流转的行星工单系统。所以根据这个处理思路,我们建立工单系统的流程控制方案。据此,我们用类管道函数实现了简单的流程控制。行为传参通过标志指定,仅能指定单行为。 1.工单系统的表格页 工单系统是一种网络软件系统,根据不同组织,部门和外部客户的需求,来由针对的管理,维护和追踪一系列的问题和请求。大多用于记录、处...

    lijy91 评论0 收藏0
  • 精读《怎么 React Hooks 造轮子》

    摘要:可以看到,这样不仅没有占用组件自己的,也不需要手写回调函数进行处理,这些处理都压缩成了一行。效果通过拿到周期才执行的回调函数。实现等价于的回调仅执行一次时,因此直接把回调函数抛出来即可。 1 引言 上周的 精读《React Hooks》 已经实现了对 React Hooks 的基本认知,也许你也看了 React Hooks 基本实现剖析(就是数组),但理解实现原理就可以用好了吗?学的是...

    Shihira 评论0 收藏0

发表评论

0条评论

JinB

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<