Async loops

Learn how to use async functions inside loops.

Use case

You must to iterate over a collection and do an async function over each item but each result is not dependant between other results. Anyway you must to await all functions are finished before to continue your execution.

Non parallelized situation

1
2
3
4
5
6
7
8
9
const foo = async items => {
const results = [];
let result;
for(const item of items){
result = await asyncFunction(item);
results.push(result);
}
return results;
}

As we can see, each iteration has an await statement that blocks execution flow until it’s finished, this is a wrong solution to our use case.

Parallelized situation

1
2
3
4
5
6
7
8
const foo = async items => {
const promises = [];
for(const item of items){
promises.push(asyncFunction(item));
}
const results = await Promise.all(promises);
return results;
}

A bit easier than the above example:

1
2
3
4
const foo = async items => {
const results = await Promise.all(items.map(asyncFunction))
return results;
}

Take a look at the code. Now we have two main differences: the execution flow is not blocked because we are pushing the promises on an array and not waiting them to be finished. After that, we use Promise.all to get results array and put it in the results variable. This is the right solution. Also we are declaring results as const because we need only one assignment so we can do it.

First solution vs Second solution

It depends on how heavy is the async function inside the loop, as you can imagine, the first solution takes more and more time when the async function grows up due to it’s blocking nature. Keep in mind that efficiency is the first thing when we are handling big data sets, so use second solution whenever you can.