串行执行promise

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

  

至此问题终于解决了!

原文地址:https://www.cnblogs.com/zhuxianguo/p/11445952.html