本週精讀的文章是 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 執行隊列,展開以下:異步
new Promise((resolve, reject) => { // Promise #1 resolve(); }) .then(result => { // Promise #2 return result; }) .then(result => { // Promise #3 return result; }); // ... and so on!
Reduce
的做用就是在內存中生成這個隊列,而不須要把這個冗餘的隊列寫在代碼裏!async
感謝 eos3tion 同窗補充,在 async/await 的支持下,runPromiseByQueue
函數能夠更爲簡化:函數
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
若是你想參與討論,請點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。