You are viewing the preview version of this book
Click here for the full version.

Async functions with forEach

The forEach function is similar to the map, but instead of transforming the values and using the results, it runs the function for each element and discards the result. Effectively, the important part is the side effects of calling the function.

For example, printing each element to the console, synchronously:

const arr = [1, 2, 3];

arr.forEach((i) => {
  console.log(i);
});

// 1
// 2
// 3

console.log("Finished sync");
// Finished sync

As the result is not important, using an async function as the iteratee would work:

const arr = [1, 2, 3];

arr.forEach(async (i) => {
  // each element takes a different amount of time to complete
  await sleep(10 - i);
  console.log(i);
});

console.log("Finished async");
// Finished async

// 3
// 2
// 1
Async forEach

Controlling the timing

Waiting for finish

But, not unsurprisingly, the function is called asynchronously, and the program execution goes past the call. This is an important difference from the sync version, as, by the time the next line is executed, the synchronous forEach is already done, while the async version is not. That's why the "Finished async" log appears before the elements.

To wait for all the function calls to finish before moving on, use a map with a Promise.all and discard the results:

const arr = [1, 2, 3];

await Promise.all(arr.map(async (i) => {
  await sleep(10 - i);
  console.log(i);
}));

// 3
// 2
// 1

console.log("Finished async");
// Finished async
Async forEach, waiting for the results

With this change, the "Finished async" comes last.

Sequential processing

But notice that the iteratee functions are called in parallel. To faithfully follow the synchronous forEach, use a reduce with an await memo first:

const arr = [1, 2, 3];

await arr.reduce(async (memo, i) => {
  await memo;
  await sleep(10 - i);
  console.log(i);
}, undefined);

// 1
// 2
// 3

console.log("Finished async");
// Finished async
Async forEach, sequential processing
There is more, but you've reached the end of this preview
Read this and all other chapters in full and get lifetime access to:
  • all future updates
  • full web-based access
  • PDF and Epub versions