顺序执行异步任务
使用 for await 和 reduce 实现异步任务的顺序执行
问题
如何让多个异步任务按顺序依次执行,而不是并发执行?
解答
方法一:for 循环 + await
普通的 for 循环是顺序执行的,配合 async/await 可以实现异步任务的顺序执行。注意 Array.forEach 和 Array.map 是并发执行的,不适用于此场景。
(async () => {
const sleep = delay => {
return new Promise((resolve) => {
setTimeout(() => resolve(), delay)
})
}
const task = (i) => {
return new Promise(async (resolve) => {
await sleep(500)
console.log(`now is ${i}`)
resolve(++i)
})
}
let result = 0
for (let i = 0; i < 4; i++) {
result = await task(result)
}
})()
输出:
now is 0
now is 1
now is 2
now is 3
方法二:Array.prototype.reduce
利用 reduce 的累积特性,将上一个异步任务的结果传递给下一个任务。
const sleep = delay => {
return new Promise((resolve) => {
setTimeout(() => resolve(), delay)
})
}
const task = (i) => {
return new Promise(async (resolve) => {
await sleep(500)
console.log(`now is ${i}`)
resolve(++i)
})
}
[task, task, task, task].reduce(async (prev, task) => {
const res = await prev
return task(res)
}, 0)
在 reduce 中:
prev是前一个异步任务返回的 Promisetask是当前要执行的异步任务- 通过
await prev获取上一个任务的结果,作为当前任务的参数
输出:
now is 0
now is 1
now is 2
now is 3
关键点
- 普通 for 循环是顺序执行的,
forEach和map是并发执行的 for + await方式简单直观,适合固定次数的循环reduce方式利用累积值传递结果,适合任务数组的场景- 每个异步任务需要等待上一个任务完成后才能执行
目录