串行的 Promise

150 阅读1分钟

Promise 的并行操作我们知道是 Promise.all()Promise.allSettled()。但是有的时候我们会有 Promise 串行请求的操作,比如一些级联组件,需要逐层的请求后端数据。这就需要自己实现 Promise 的串行请求操作了。

for of 实现

const asyncFunc = (data) => new Promise((resolve, reject)=>{
  setTimeout(()=>{
    console.log(`${data} ${dayjs().format('HH:mm:ss')}`)
    resolve()
  }, 1000)
})

async function serialFun(arr){
  for(let data of arr){
    console.log(`for of ${data}`)
    await asyncFunc(data)
  }
}

serialFun([1,2,3])

image.png

当然使用 for(let i=0;i<length;i++) 循环也是可以的

reduce

const asyncFunc = (data) => new Promise((resolve, reject)=>{
  setTimeout(()=>{
    console.log(`${data} ${dayjs().format('HH:mm:ss')}`)
    resolve()
  }, 1000)
})
const list = [1,2,3]

 function serialFun(arr){
  arr.reduce(async (accumulatorPromise, data)=>{
    console.log(`reduce ${data}`)
    await accumulatorPromise
    return asyncFunc(data)
  }, Promise.resolve())
}

serialFun(list)

image.png

不正确的写法

const asyncFunc = (data) => new Promise((resolve, reject)=>{
  setTimeout(()=>{
    console.log(`${data} ${dayjs().format('HH:mm:ss')}`)
    resolve()
  }, 1000)
})

 function serialFun(arr){
  arr.forEach(async data=>{
    console.log(`forEach ${data}`)
    await asyncFunc(data)
  })
}

serialFun([1,2,3])

image.png

事实上,
Array.prototype.forEach()
Array.prototype.map()
Array.prototype.filter()
Array.prototype.some()
Array.prototype.every()
这些函数都不支持异步等待。

# 执行机制 - 使用Promise实现串行
# Why Using reduce() to Sequentially Resolve Promises Works
# 精读《用 Reduce 实现 Promise 串行执行》