Promise提供了Promise.all,Promise.race,Promise.allSettled等多個Promise對象間的運行關系,如果並行運行可以用Promise.all來進行處理,如果要串行運行可以用數組的reduce來進行處理,處理代碼如下:
const serialPromises = function (promises) { promises.reduce((prev, next) => prev.then((preVal) => next(preVal)), Promise.resolve()); }
測試代碼
const fn1 = function (args) { console.log('fn1',args) return Promise.resolve('111') } const fn2 = function (args) { console.log('fn2',args) return Promise.resolve('222') } const fn3 = function (args) { console.log('fn3',args) return Promise.resolve('333') } serialPromises([fn1, fn2, fn3])
測試結果:
fn1 undefined fn2 111 fn3 222
上面serialPromises有個問題如果有個fn2執行reject那么執行鏈會發生中斷
測試代碼
const fn1 = function (args) { console.log('fn1',args) return Promise.resolve('111') } const fn2 = function (args) { console.log('fn2',args) return Promise.reject('222') } const fn3 = function (args) { console.log('fn3',args) return Promise.resolve('333') } serialPromises([fn1, fn2, fn3])
測試結果
fn1 undefined fn2 111 Uncaught (in promise) 222
改進一下
const serialPromises2 = function (promises) { promises.reduce((prev, next) => prev.then(next).catch(next), Promise.resolve()); }
測試代碼
const fn1 = function (args) { console.log('fn1',args) return Promise.resolve('111') } const fn2 = function (args) { console.log('fn2',args) return Promise.reject('222') } const fn3 = function (args) { console.log('fn3',args) return Promise.resolve('333') } serialPromises2([fn1, fn2, fn3])
測試結果
fn1 undefined fn2 111 fn2 222 fn3 222
這個方法也有個問題是如果有fn2執行reject,那么那個fn2會執行兩次,這是因為p.catch等價於p.then(undefined, onRejected)
我們再次改進
const serialPromises3=function(promises){ const process=function(i,args){ const curr=promises[i] const next=function(res){process(i+1,res)} if(curr)curr(args).then(next).catch(next) } process(0) }
測試代碼
const fn1 = function (args) { console.log('fn1',args) return Promise.resolve('111') } const fn2 = function (args) { console.log('fn2',args) return Promise.reject('222') } const fn3 = function (args) { console.log('fn3',args) return Promise.resolve('333') } serialPromises3([fn1, fn2, fn3])
測試結果
fn1 undefined fn2 111 fn3 222
至此問題終於解決了!