JavaScript: async/await with forEach()

Sebastien Chopin
codeburst
Published in
2 min readOct 5, 2017

--

A beautiful picture of a waterfall (by Jeffrey Workman)

async/await is freaking awesome, but there is one place where it’s tricky: inside a forEach()

Let’s try something:

const waitFor = (ms) => new Promise(r => setTimeout(r, ms));[1, 2, 3].forEach(async (num) => {
await waitFor(50);
console.log(num);
});
console.log('Done');

If you run this code with node.js (≥ 7.6.0), this will happen:

$ node forEach.js
$ Done

What?

console.log(num) are not displayed into the console.

Let’s re-create forEach() to understand what’s happening:

Array.prototype.forEach = function (callback) {
// this represents our array
for (let index = 0; index < this.length; index++) {
// We call the callback for each entry
callback(this[index], index, this);
}
};

The real polyfill of forEach()is available at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill

As you can see, thecallback is called but we are not waiting for it to be done before going to the next entry of the array.

We can solve this by creating our own asyncForEach() method:

async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}

Then, we can update our example to use our asyncForEach method:

asyncForEach([1, 2, 3], async (num) => {
await waitFor(50);
console.log(num);
})
console.log('Done');

By running this code into node, we can now see:

$ node forEach.js
$ Done
$ 1
$ 2
$ 3

We’re getting closer!

Actually, our asyncForEach returns a Promise (since it’s wrapped into an asyncfunction) but we are not waiting for it to be done before logging ‘Done’.

Let’s update our example again to wrap our execution into an async method:

const start = async () => {
await asyncForEach([1, 2, 3], async (num) => {
await waitFor(50);
console.log(num);
});
console.log('Done');
}
start();

Let’s run it one last time:

$ node forEach.js
$ 1
$ 2
$ 3
$ Done

🎉 We now have a way of using forEach with async/await 🎉

You can see the full code on https://gist.github.com/Atinux/fd2bcce63e44a7d3addddc166ce93fb2

Credit: Photo taken from https://unsplash.com/photos/YvkH8R1zoQM

--

--