07-21-2023, 03:01 PM
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][1]:
> 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.
[1]:
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][1]:
> 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.
[1]:
[To see links please register here]