利用async/await與forEach循環進行操作
P粉010967136
P粉010967136 2023-08-20 11:27:20
0
2
557
<p>在使用 <code>forEach</code> 循環中使用 <code>async</code>/<code>await</code> 會有問題嗎?我試圖遍歷一個文件數組,並在每個文件的內容上使用 <code>await</code>。 </p> <pre class="brush:php;toolbar:false;">import fs from 'fs-promise' async function printFiles () { const files = await getFilePaths() // 假設這個函數正常運作 files.forEach(async (file) => { const contents = await fs.readFile(file, 'utf8') console.log(contents) }) } printFiles()</pre> <p>這段程式碼確實可以運作,但這樣做會有什麼問題嗎?有人告訴我在像這樣的高階函數中不應該使用 <code>async</code>/<code>await</code>,所以我想問是否有任何問題。 </p>
P粉010967136
P粉010967136

全部回覆(2)
P粉697408921

使用ES2018,您可以大幅簡化上述所有答案:

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

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

查看規格:proposal-async-iteration

#簡化後:

#
for await (const results of array) {
    await longRunningTask()
  }
  console.log('I will wait')

2018-09-10:最近這個答案引起了很多關注,請參閱Axel Rauschmayer的部落格文章以獲取有關非同步迭代的更多資訊。

P粉094351878

當然,程式碼確實可以工作,但我很確定它不會按照你的期望工作。它只是觸發了多個非同步調用,但printFiles函數在此之後立即返回。

按順序讀取

如果你想按順序讀取文件,確實不能使用forEach。相反,你可以使用現代的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);
  }
}

並行讀取

如果你想並行讀取文件,確實不能使用forEach。每個async回呼函數呼叫都會傳回一個promise,但你卻將它們丟棄而不是等待它們。相反,你可以使用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)
  }));
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板