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
至此问题终于解决了!