The async and await keywords have been a part of JavaScript for a while, and Node and all major browsers fully support them. Although they have been extensively written about, many new JavaScript and Node developers are still unsure of how to use them.

Use an async function that waits for the promises to finish before resuming iteration to make Javascript promises operate in for loops. To use Javascript promises in a for loop, use async/await.
Here is a sample of the appropriate code:

				
					async function doSomething() {
    for (item of items) {
        await promiseAction(item)
    }
}
				
			

Before moving on to the next iteration of the loop, this waits for each promiseAction to finish.
Here is the erroneous strategy that you were likely envisioning as a comparison:

				
					function doSomething() {
    for (item of items) {
       promiseAction(item)
    }
}
				
			

You may discover how async/await functions in this manual and how it circumvents the issue of promises in for loops. Promises are used in for loops, but by default the loop does not wait for the promises to be resolved or rejected.

This results in strange behavior. For instance, you might find yourself attempting to access values that are not yet available. Make the loop wait for the asynchronous activities to finish in order to fix this issue. Async/await allows for this.

The Fix: Async/Await

On each iteration of the for loop, your loop must wait for the asynchronous task to finish.

Use the async keyword to make your function asynchronous, then put the await keyword in front of the action you want to wait for, to make this happen.

Let’s look at an example where we first attempt to execute asynchronous code as synchronous code. Next, let’s use async/await to resolve the problem.

Example

Let’s imagine that we are sending a lot of emails.

An asynchronous task that takes an unknown amount of time to accomplish is sending an email online.

In this example, we create a system for email delivery notifications. Additionally, the system alerts us once more after every email has been sent successfully.

				
					Mail sent to adam@gmail.com
Mail sent to ben@gmail.com
Mail sent to charls@gmail.com
All emails were sent
				
			

To simulate this, let’s create:

  • An array of email addresses.
  • A method that resolves a promise after a one-second wait to mimic sending an email.
  • A method that sends each email in the array of email addresses while also notifying us.

Here is an improper strategy that ignores the asynchronous nature of this task:

				
					const emails = ['adam@gmail.com', 'ben@gmail.com', 'charls@gmail.com'];

const send = email =>
  new Promise(resolve =>
    setTimeout(() => resolve(email), 1000)
  );

const sendAllEmails = () => {
  for (email of emails) {
    const emailInfo = send(email);
    console.log(`Mail sent to ${emailInfo}`);
  }

  console.log('All emails were sent');
};

sendAllEmails();
				
			

An unexpected output is produced when this code is run:

				
					Mail sent to [object Promise]
All emails were sent
				
			

These notifications are printed to the console without any delay.

What went wrong, then?

Our code runs synchronously, but the tasks are asynchronous, which causes a problem. The for loop does not hold off on sending the messages. Instead, it immediately sends each mail.

So you need to make the for loop wait for each message to be sent.

To do this:

  • Make the sending of emails asynchronous.
  • Wait for each send operation to be finished.

To turn this idea into code:

  • Mark the sendAllEmails() function async. This tells JavaScript that the function is an asynchronous.
  • Wait for the send() function to complete using await keyword.

This revised code is provided:

				
					const emails = ['adam@gmail.com', 'ben@gmail.com', 'charls@gmail.com'];

const send = email =>
  new Promise(resolve =>
    setTimeout(() => resolve(email), 1000)
  );

const sendAllEmails = async () => {
  for (email of emails) {
    const emailInfo = await send(email);
    console.log(`Mail sent to ${emailInfo}`);
  }

  console.log('All emails were sent');
};

sendAllEmails();
				
			

Now, this results in the desired output:

				
					Mail sent to adam@gmail.com
Mail sent to ben@gmail.com
Mail sent to charls@gmail.com
All emails were sent
				
			

Wrap up

Today you learnt how to make Javascript promises operate in a for loop using async/await. To recap, mark the asynchronous function async, and wait for the asynchronous action to complete with await.


Thanks for reading. Happy coding!