本周精读的文章是 why-using-reduce-to-sequentially-resolve-promises-works,讲了如何利用 reduce 实现 Promise 串行执行。javascript
在 async/await 之前 Promise 串行执行仍是比较麻烦的,但愿根据这篇文章能够理清楚串行 Promise 的思惟脉络。css
除了依赖 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 回调函数的第一个参数,直到队列循环完毕,所以能够进行累加计算。java
那么将 reduce
的特性用在 Promise 试试:git
function runPromiseByQueue(myPromises) {
myPromises.reduce(
(previousPromise, nextPromise) => previousPromise.then(() => nextPromise()),
Promise.resolve()
);
}
复制代码
当上一个 Promise 开始执行(previousPromise.then
),当其执行完毕后再调用下一个 Promise,并做为一个新 Promise 返回,下次迭代就会继续这个循环。github
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
promise 1
promise 2
promise 3
复制代码
Reduce
是同步执行的,在一个事件循环就会完成(更多请参考 精读《Javascript 事件循环与异步》),但这仅仅是在内存快速构造了 Promise 执行队列,展开以下:bash
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
async function runPromiseByQueue(myPromises) {
for (let value of myPromises) {
await value();
}
}
复制代码
多亏了 async/await,代码看起来如此简洁明了。
不过要注意,这个思路与 reduce
思路不一样之处在于,利用 reduce
的函数总体是个同步函数,本身先执行完毕构造 Promise 队列,而后在内存异步执行;而利用 async/await 的函数是利用将本身改造为一个异步函数,等待每个 Promise 执行完毕。
天猪 同窗分享的 promise-fun 除了串行 Promise 解决方案,还提供了一系列 Promise 功能拓展(有一些逐渐被 ES 标准采纳,好比 finally 已经进入 Stage 4),若是你的项目还没法使用 async/await,是不须要本身从新写一遍的,固然本文的原理仍是须要好好理解。
Stage 相关能够进行拓展阅读 精读《TC39 与 ECMAScript 提案》。
Promise 串行队列通常状况下用的很少,由于串行会阻塞,而用户交互每每是并行的。那么对于并行发请求,前端按串行顺序接收 Response 也是一个有意思的话题,留给你们思考。
讨论地址是:精读《用 Reduce 实现 Promise 串行执行》 · Issue #109 · dt-fe/weekly
若是你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。