Skip to content

如何顺序执行10个异步任务?

参考答案:

解法1:for 循环 + await

简单的 for 循环是依次进行循环的,不像 Array.forEach,Array.map 方法是并发执行的,利用这一特点加 async / await 很容易写出下面这样的代码:

js
(async () => {
  const sleep = delay => {
    return new Promise((resolve, reject) => {
      setTimeout(_ => resolve(), delay)
    })
  }
  
  const task = (i) => {
    return new Promise(async (resolve, reject) => {
      await sleep(500)
      console.log(`now is ${i}`)
      ++i
      resolve(i)
    })
  }
  
  let param = 0
  for (let i = 0; i < 4; i++) {
    param = await task(param)
  }  
})()

输出:

now is 0
now is 1
now is 2
now is 3

解法2:Array.prototype.reduce

关于 Array.prototype.reduce 方法相信大部分小伙伴初见时都是用来数组求和。

reduce有初始值积累值,以及当前值的概念。其中 积累值可以看作是前一个值,通过返回积累值又可以看作是 下一个值。使用reduce来解决问题的代码为:

js
const sleep = delay => {
  return new Promise((resolve, reject) => {
    setTimeout(_ => resolve(), delay)
  })
}

const task = (i) => {
  return new Promise(async (resolve, reject) => {
    await sleep(500)
    console.log(`now is ${i}`)
    ++i
    resolve(i)
  })
}

[task, task, task, task].reduce(async (prev, task) => {
  const res = await prev
  return task(res)
}, 0)

输出:

now is 0
now is 1
now is 2
now is 3

可以这样理解 prevtask

  • prev:前一个 异步任务(promise)
  • task:当前的异步任务

当前的异步任务需要上一个异步任务的结果作参数,故很显然要 await prev。

题目要点:

解法1:for 循环 + await

使用 for 循环结合 async/await 可以实现顺序执行异步任务:

  • 特点:通过 for 循环的顺序性,确保了每个 task 函数都是在前一个任务完成后才执行。

解法2:Array.prototype.reduce

使用 reduce 方法也可以实现异步任务的顺序执行,其原理是利用 reduce 的累加器功能

  • 特点reduce 方法中的 prev 代表前一个异步任务的结果,task 是当前的异步任务。通过 await prev 确保了任务的顺序执行。

这两种解法都有效地处理了异步任务的顺序执行问题,但它们在代码结构和执行逻辑上有所不同。for 循环 + await 更直观易懂,而 reduce 方法则提供了一种更函数式编程的解决方案。在实际应用中,可以根据具体需求和偏好来选择使用哪种方法。