Blog / Javascript

Is JavaScript forEach async?

Is JavaScript forEach async?

In this post you will find out the answer to the question of is JavaScript forEach async, or not what the alternatives are, and how you can use them all with examples.

Will MaygerWill Mayger
September 08, 2021
Article

There is some confusion around using async/await with a JavaScript forEach loop, and whether or not it is asynchronous, what the alternatives are and how to use them.

In this post we will cover everything you need to know about asynchronous looping and answer the question of is JavaScript forEach async, and if not what alternatives you have.

Is JavaScript forEach async?

No. The JavaScript Array.prototype.forEach loop is not asynchronous. The Array.prototype.forEach method accepts a callback as an argument which can be an asynchronous function, but the forEach method will not wait for any promises to be resolved before moving onto the next iteration.

If you need to wait for iterations to complete and finish, then you will be better off using a for loop, which will be explained later on in this post.

The confusion comes from where it is possible to still pass in asynchronous functions that can perform asynchronous actions because the forEach loop accepts a callback as an argument.

The reason why the forEach loop itself is not async is because it will not wait for these functions to resolve (return with the value after the async operation has been finished).

What this means is that whilst you can pass an asynchronous function as the callback, the actual forEach loop will not wait for your function because it does not consider it as asynchronous and just thinks of it as a normal function.

Here is an example of this issue when using async/await with a forEach loop:

const delay = async (ms = 1000) =>
  new Promise(resolve => setTimeout(resolve, ms))

[1, 2, 3].forEach(async num => {
  await delay()
  console.log(num)
})
// after 1 second
// 1
// 2
// 3
Behaviour of async function in non async forEach

As you can see in this example the behaviour is not as you might have expected.

Instead of there being a delay between each iteration, there appears to be a single delay and then all the functions happen at the same time.

There are still the same amount of delays happening but they all start at the same time and end at the same time because the forEach loop does not wait for async callbacks.

To emulate the expected behaviour you would have to modify the delay function by factoring this in.

You could use the array index as a multiplier so even though all the array item delays get triggered at the same time, they will all have different lengths of delays based on the index.

Here is an example of this:

const delay = async (ms = 1000) =>
  new Promise(resolve => setTimeout(resolve, ms))

[1, 2, 3].forEach(async (num, index) => {
  await delay(index * 1000)
  console.log(num)
})
// 1
// 1 second later
// 2
// 1 second later
// 3
javascript foreach async

However this only works in the above example because we can control the delay, this won’t work if you are instead making an async request because it can complete at any point which is outside of our control.

If you still need to create an async loop in JavaScript there are other options that you can use such as a for loop or map instead of the JavaScript Array.prototype.forEach method.

How to create a JavaScript async for loop

One of the best alternatives to create an asynchronous loop is to use a JavaScript for loop.

It can be used in the same way as you ordinarily would write your async code, so all you have to do is ensure that you are writing your async code within an async function and it will work.

Using the above example, let’s create another example but this time of how to create a JavaScript async for loop:

(async () => {
  const delay = async (ms = 1000) =>
    new Promise(resolve => setTimeout(resolve, ms))

  const myArray = [1, 2, 3]

  for (let i = 0; i < myArray.length; i += 1) {
    await delay()
    console.log(myArray[i])
  }
})()
// 1
// 1 second later
// 2
// 1 second later
// 3
javascript async for loop

As you can see by using a for loop it works in the way in which we would expect by waiting for each iteration to complete before moving onto the next.

It is important to remember that this code is working because we have wrapped everything in an async IIFE(Immediately invoked function expression) which is just a way of saying that it is wrapped in an async function that gets called immediately.

The async function wrapper is needed to allow the use of async code.

Summary

There we have is JavaScript forEach async, if you want more like this be sure to check out some of my other posts!

Foxi - Budget Planner & Tracker

Foxi

Budget Planner & Tracker

More money in your pocket by the end of the month.

Free to use and no account needed.

Get started now.

Get the app

Some graphics used on this post were made using icons from flaticon.

Latest Posts

Learn React, JavaScript and TypeScript

Learn React, JavaScript and TypeScript

Join the platform that top tier companies are using.
Master the skills you need to succeed as a software engineer and take your career to the next level with Pluralsight.

Start here

Become an expert in ReactJS, TypeScript, and JavaScript.

Here you will find my personal recomendations to you, for full disclosure I earn a small commission from some of these links, but I only recommend what I trust and personally use.

Good things are coming, don't miss out!

Good things are coming, don't miss out!

Follow me on Twitter to stay up to date and learn frontend, React, JavaScript, and TypeScript tips and tricks!

Are you a novice, intermediate or expert react engineer?

Find out here by taking my fun, interactive, quick quiz which takes approximately 1 - 3 minutes. How well will you will do?

Foxi - Budget Planner & Tracker

Foxi

Budget Planner & Tracker

More money in your pocket by the end of the month.

Free to use and no account needed.

Get started now.

Get the app