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])
当然使用 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)
不正确的写法
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])
事实上,
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 串行执行》