JS Tip: #1 - async/await sobre arrays

devjosemanuel

DevJoseManuel

Posted on May 3, 2022

JS Tip: #1 - async/await sobre arrays

Supongamos que, por la razón que sea, estamos recorriendo un array con el método map() y que tenemos que ejecutar una función asíncrona en cada uno de los elementos. Algo como lo siguiente:

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

lo que tenemos que entender aquí es que la función ficticia fetchApiData (la cual recibe como parámetro el nombre de uno de un usuario) estará realizando una llamada asíncrona a una API externa con la que trabaja nuestra aplicación.

¿Qué ocurre si ahora a continuación escribimos el contenido de la variable data por la consola? Pues que nos vamos a encontrar con algo como lo siguiente:

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

Es decir, que la ejecución del código no se para a la espera de recibir los resultados de la llamada a la API externa y por lo tanto el array data estará formado por tantos elementos como usuarios hemos declarado en el array users y asociados a cada una de las posiciones un objeto Promise de JavaScript en el estado pending.

Resolución de todas las llamadas en paralelo.

La primera de las opciones que tenemos para poder solucionar este problema pasa por utilizar el método all() del objeto Promise de JavaScript el cual va a permitir que todas las promesas que recibe como parámetro (este método espera recibir como parámetro un array de promesas que se deben resolver) pasan a ser ejecutadas en paralelo, sin depender unas de otras, y no finaliza su ejecución hasta que todas estas promesas hayan finalizado.

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

Al ejecutarse en paralelo tenemos que entender que el tiempo de ejecución total del método será el de la promesa que consume más tiempo de resolucíón, lo cual lo hace una alternativa muy rápida cuando no hay una dependencia entre promesas.

Resolución de las llamas de forma secuencial.

Pero ¿qué ocurrirá en el caso de que tengamos una dependencia en la ejecución de las promesas, es decir, que las llamadas a la función asíncrona (en nuestro ejemplo la API externa dependerán del resultado de la llamada anterior)? Es este caso deberemos utilizar la estructura for ... of como sigue:

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

En este caso es fácil entender que, como una llamada depende de la anterior, el resultado de la ejecución de todo el código será la suma de la resolución de cada una de las promesas por separado.

💖 💪 🙅 🚩
devjosemanuel
DevJoseManuel

Posted on May 3, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Preguntas de Entrevista JS
javascript Preguntas de Entrevista JS

August 8, 2021