As other answers have mentioned, you're probably wanting it to be executed in sequence rather in parallel. Ie. run for first file, wait until it's done, then once it's done run for second file. That's not what will happen.
I think it's important to address why this doesn't happen.
Think about how forEach
works. I can't find the source, but I presume it works something like this:
const forEach = (arr, cb) => {
for (let i = 0; i < arr.length; i++) {
cb(arr[i]);
}
};
Now think about what happens when you do something like this:
forEach(files, async logFile(file) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
});
Inside forEach
's for
loop we're calling cb(arr[i])
, which ends up being logFile(file)
. The logFile
function has an await
inside it, so maybe the for
loop will wait for this await
before proceeding to i++
?
No, it won't. Confusingly, that's not how await
works. From the docs:
An await splits execution flow, allowing the caller of the async function to resume execution. After the await defers the continuation of the async function, execution of subsequent statements ensues. If this await is the last expression executed by its function execution continues by returning to the function's caller a pending Promise for completion of the await's function and resuming execution of that caller.
So if you have the following, the numbers won't be logged before "b"
:
const delay = (ms) => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};
const logNumbers = async () => {
console.log(1);
await delay(2000);
console.log(2);
await delay(2000);
console.log(3);
};
const main = () => {
console.log("a");
logNumbers();
console.log("b");
};
main();
Circling back to forEach
, forEach
is like main
and logFile
is like logNumbers
. main
won't stop just because logNumbers
does some await
ing, and forEach
won't stop just because logFile
does some await
ing.