Question
Are there any issues with using async
/await
in a forEach
loop? I'm
trying to loop through an array of files and await
on the contents of each
file.
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()
This code does work, but could something go wrong with this? I had someone
tell me that you're not supposed to use async
/await
in a higher-order
function like this, so I just wanted to ask if there was any issue with this.
Answer
Sure the code does work, but I'm pretty sure it doesn't do what you expect it
to do. It just fires off multiple asynchronous calls, but the printFiles
function does immediately return after that.
Reading in sequence
If you want to read the files in sequence, you cannot useforEach
indeed.
Just use a modern for … of
loop instead, in which await
will work as
expected:
async function printFiles () {
const files = await getFilePaths();
for (const file of files) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}
}
Reading in parallel
If you want to read the files in parallel, you cannot useforEach
indeed.
Each of the async
callback function calls does return a promise, but you're
throwing them away instead of awaiting them. Just use map
instead, and you
can await the array of promises that you'll get with Promise.all
:
async function printFiles () {
const files = await getFilePaths();
await Promise.all(files.map(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
}));
}