Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save anonimusprogramus/120c651d387a585d56d8617076cc9882 to your computer and use it in GitHub Desktop.

Select an option

Save anonimusprogramus/120c651d387a585d56d8617076cc9882 to your computer and use it in GitHub Desktop.
Do not use forEach with async-await
`Array.prototype.forEach` can not be used for asynchronous code. (It could not be used with promises, and it can not be used with async-await.)
The following forEach loop might not do what it looks like:
```js
const players = await this.getWinners();
players.forEach(async (player) => {
await givePrizeToPlayer(player);
});
await sendEmailToAdmin('All prizes awarded');
```
What's wrong with it?
- The promises returned by the iterator function are not handled. If one of them throws an error, the error won't be caught.
- The prizes are awarded in parallel, not serial (one by one).
- The loop finishes iterating before any of the prizes have been given.
- As a result, sendEmailToAdmin sends the email before the prizes have been awarded.
## So how to do it?
### Process each player in serial
```js
for (const player of players) {
await givePrizeToPlayer(player);
}
```
### Process all the players in parallel
```js
await Promise.all(players.map(async (player) => {
await givePrizeToPlayer(player);
}));
```
### Process each player in serial, using `Array.prototype.reduce`
```js
await players.reduce(async (a, player) => {
await a;
await givePrizeToPlayer(player);
}, Promise.resolve());
```
Some people recommend this approach as more "functional" but I find the `for-of` loop is clearer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment