如何处理循环的异步操作

假如存在如下异步任务队列,有哪些方式可以去循环处理这个异步队列。

// 模拟异步任务队列
// 异步任务:每个异步任务的执行时机都是1s后
const tasks = Array.from({ length: 5 }).map(
  (_, index) => () => new Promise((resolve) => setTimeout(resolve, 1000)),
);

使用Promise.all

Promise.all可以一次处理多个Promise任务,我们可以利用这个特性实现异步任务队列的循环。

这是一个并行的任务,它的结束时间由执行时间最长的一个异步任务决定。

console.log('任务处理开始');
Promise.all(
  tasks.map((task, index) =>
    task().then(() => {
      console.log(`执行任务 ${index}`);
    }),
  ),
).then(() => {
  console.log('任务处理结束');
});

使用for await...of

for await...of可以去遍历上述形式的异步队列,和Promise.all类似,这也是一个并行任务。关于for await...of的语法可以参见MDN

(async function runTask() {
  console.log('任务处理开始');
  for await (const taskIndex of tasks.map((t, index) => t().then(() => index))) {
    console.log(`执行任务 ${taskIndex}`);
  }
  console.log('任务处理结束');
})();

使用async/await

使用await关键字,表示函数会等待await后面的异步执行完成才会继续向下执行,所以,我们可以将await放在异步循环中,如果这个循环没有结束,那么函数后面的代码将不会执行。

和上述的几种写法不同,这是一种串行执行的方式,它的每一个任务必须要等上一个任务执行结束才会执行,所以它的执行时间是所有任务执行时间的总和。

(async function runTask() {
  console.log('任务处理开始');
  for (const [index, task] of tasks.entries()) {
    await task();
    console.log(`执行任务 ${index}`);
  }
  console.log('任务处理结束');
})();
如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注