Shane Bartholomeusz

Geek and lover of all things tech related

Solved: Why Async/Await does not work with .forEach

The Problem

Javascript offers a number of different ways to iterate over an array. Recently while using the array.forEach syntax, I came across some interesting behaviour when using them with the async/await syntax.

To demonstrate. Lets take the following Javascript code which simply prints some messages to the console every 2 seconds.

Javascript Icon
function waitForTwoSecs(i) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`loop iteration ${i}`); 
      resolve('resolved');
    }, 2000);
  });
}

async function mainProgram() {
  const loopIterations = [1, 2, 3];
  console.log('mainProgram Start');

  loopIterations.forEach(async iteration =>  {
    const result = await waitForTwoSecs(iteration);
  });

  console.log('mainProgram finished'); 
}

mainProgram();

You may have expected to see the following output in the console after running the above code. Basically, the main ‘mainProgram’ function should only terminate once it has looped through all items in the array.

mainProgram Start
loop iteration 1
loop iteration 2
loop iteration 3
mainProgram finished

However, what we actually get is this. You’ll notice that the function completes execution, and then the items are iterated over. What the!

mainProgram Start
mainProgram finished
loop iteration 1
loop iteration 2
loop iteration 3

The Solution

It turns out that the array.forEach method only accepts a synchronous function, and therefore is NOT compatible with the async/await syntax.

Instead, you can use the for … of iterator as per below which is compatible with the async/await syntax.

function waitForTwoSecs(i) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`loop iteration ${i}`); 
      resolve('resolved');
    }, 2000);
  });
}

async function mainProgram() {
  const loopIterations = [1, 2, 3];
  console.log('mainProgram Start');

  for (const iteration of loopIterations) {
    const result = await waitForTwoSecs(iteration);
  };

  console.log('mainProgram finished'); 
}

mainProgram();

This will return the following results as expected.

mainProgram Start
loop iteration 1
loop iteration 2
loop iteration 3
mainProgram finished

Final Thoughts

Well I hope that you’ve learned something new from the article, as I have inadvertently recently done!

If you have any comments or suggestions, please feel free to share them below. Happy coding 🙂

Shane Bartholomeusz

1 Comment

  1. Worked perfectly

Leave a Reply

© 2024 Shane Bartholomeusz

Theme by Anders NorenUp ↑