Skip to content

如何正确的使用 async/await 和 forEach 循环

Posted on:2023年10月29日 at 00:23

async/await 是 JavaScript 中用于处理异步操作的一种语法糖。它可以使异步代码看起来更像同步代码,从而更容易阅读和编写。

forEach 是一种用于遍历数组的方法。它接受一个回调函数作为参数,并对数组中的每个元素调用该函数。

async/await 不能直接用于 forEach 循环中,因为 forEach 不会等待回调函数返回的 Promise 完成。如果在 forEach 中使用 async/await,循环将不会等待异步操作完成就开始下一个迭代。这会导致意想不到的行为,如果您希望每个迭代在开始下一个迭代之前完成。

要修复此问题,您可以使用 for 循环、for…of 循环或 map() 函数与 async/await 一起使用,以实现所需的异步行为。

以下是在 forEach 循环中使用 async/await 的示例:

// 注意!这是无效的代码!
const files = await getFilePaths();

files.forEach(async file => {
  const contents = await fs.readFile(file, "utf8");
  console.log(contents);
});

这段代码可能不会做您期望的事情。它只是启动多个异步调用,但并不等待异步操作完成。

要按顺序读取文件,只需使用一个现代的 for…of 循环,其中 await 将按预期工作:

async function printFiles() {
  const files = await getFilePaths();

  for (const file of files) {
    const contents = await fs.readFile(file, "utf8");
    console.log(contents);
  }
}

要并行读取文件,您只需使用 map,您就可以等待使用 Promise.all 获得的 Promise 数组:

async function printFiles() {
  const files = await getFilePaths();

  await Promise.all(
    files.map(async file => {
      const contents = await fs.readFile(file, "utf8");
      console.log(contents);
    })
  );
}