在foreach循环中使用async/await

euoag5mw  于 2021-10-10  发布在  Java
关注(0)|答案(19)|浏览(500)

使用时有什么问题吗 async / await 在一个 forEach 环我正在尝试循环浏览一系列文件和 await 关于每个文件的内容。

import fs from 'fs-promise'

async function printFiles () {
  const files = await getFilePaths() // Assume this works fine

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

printFiles()

这段代码确实有效,但会不会出问题?有人告诉我你不能用 async / await 在像这样的高阶函数中,我只是想问一下这是否有什么问题。

vwoqyblh

vwoqyblh16#

这里有一些 forEachAsync 原型。请注意,您需要 await 他们:

Array.prototype.forEachAsync = async function (fn) {
    for (let t of this) { await fn(t) }
}

Array.prototype.forEachAsyncParallel = async function (fn) {
    await Promise.all(this.map(fn));
}

注意:虽然您可以在自己的代码中包含这一点,但您不应该在分发给其他人的库中包含这一点(以避免污染他们的全局)。

x6492ojm

x6492ojm17#

npm上的p-iteration模块实现了数组迭代方法,因此它们可以以非常简单的方式与async/await一起使用。
您的案例示例如下:

const { forEach } = require('p-iteration');
const fs = require('fs-promise');

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

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

bpsygsoo18#

而不是 Promise.all 结合 Array.prototype.map (这并不保证 Promise 解决了),我使用 Array.prototype.reduce ,从已解决的 Promise :

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

  await files.reduce(async (promise, file) => {
    // This line will wait for the last async function to finish.
    // The first iteration uses an already resolved Promise
    // so, it will immediately continue.
    await promise;
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }, Promise.resolve());
}
cmssoen2

cmssoen219#

使用es2018,您可以大大简化上述所有答案:

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

  for await (const contents of files.map(file => fs.readFile(file, 'utf8'))) {
    console.log(contents)
  }
}

参见规范:提案异步迭代
2018-09-10:这个答案最近引起了很多关注,有关异步迭代的更多信息,请参阅axel rauschmayer的博客文章。

相关问题