DEV Community

Cover image for JS Tip: #1 - async/await over arrays
DevJoseManuel
DevJoseManuel

Posted on • Updated on

JS Tip: #1 - async/await over arrays

Suppose that, for whatever reason, we are traversing an array with the map() method and we have to execute an asynchronous function on each of the elements. Something like the following:

const users = ['user1', 'user2', 'user3']
const data = users.map(async (user) => await fetchApiData(user))
Enter fullscreen mode Exit fullscreen mode

What we need to understand here is that the dummy function fetchApiData (which receives as parameter the name of one of a user) will be making an asynchronous call to an external API that our application works with.

What happens if we now write the content of the data variable through the console? Well, we are going to find something like the following:

const users = ['user1', 'user2', 'user3']
const data = users.map(async (user) => await fetchApiData(user))

console.log(data)
/*
[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]
*/
Enter fullscreen mode Exit fullscreen mode

That is, the execution of the code does not stop waiting for the results of the external API call and therefore the array data will be formed by as many elements as users we have declared in the array users and associated to each of the positions a JavaScript Promise object in the pending state.

Resolution of all calls in parallel.

The first option we have to solve this problem is to use the all() method of the JavaScript Promise object, which will allow all the promises it receives as parameter (this method expects to receive as parameter an array of promises to be resolved) to be executed in parallel, without depending on each other, and it does not finish its execution until all these promises have finished.

const users = ['user1', 'user2', 'user3']
const data = await Promise.all(
    users.map(async (user) => await fetchApiData(user))
)

console.log(data)
/*
[
  dataFromUser1,
  dataFromUser2,
  dataFromUser3
]
*/
Enter fullscreen mode Exit fullscreen mode

When running in parallel we have to understand that the total execution time of the method will be that of the promise that consumes more resolution time, which makes it a very fast alternative when there is no dependency between promises.

Resolution of flames sequentially.

But what will happen if we have a dependency in the execution of the promises, i.e. the calls to the asynchronous function (in our example the external API will depend on the result of the previous call)? In this case we should use the structure for ... of structure as follows:

const users = ['user1', 'user2', 'user3']
const data = []

for (const user of users) {
    data.push(await fetchApiData(user))
}

console.log(data)
/*
[
  dataFromUser1,
  dataFromUser2,
  dataFromUser3
]
*/
Enter fullscreen mode Exit fullscreen mode

In this case it is easy to understand that, as one call depends on the previous one, the result of the execution of all the code will be the sum of the resolution of each of the promises separately.

Top comments (0)