Bucles asíncronos en javascript
Muchas veces hay ciertas situaciones que hacen que me plantee si esto de programar es para mí, sobre todo cuando, despues de un debug largo y tedioso, te das cuenta que lo que pasaba o era una chorrada o fallo mío por no conocer los internals del lenguaje correspondiente.
Quiero pensar que en mayor o menor medida le pasa alguna vez a todo el mundo.
En este caso he perdido las yemas de los dedos de tanto console.log
que creo que podría ir a por el récord Guinness. En la lógica de un compoenente Vue al que me ha tocado meterle mano hay una situación un tanto graciosa. Tengo que hacer varias llamadas AJAX en el método mounted()
para recoger datos de un API.
Nada fuera de lo común. Digamos que tengo un id de competición y tengo que llamar a un endpoint en el que que, dado ese id, me devuelve el nombre de la competición. Una vez conozco el nombre, tengo que llamar a otro endpoint que me devuelva un listado de rondas que tiene esa competición. Y por último, dado ese listado de rondas, hacer una tercera llamada que, por cada ronda, me facilite el listado de deportistas que van a competir.
Tengo que definir el método como asíncrono para poder hacer que unas peticiones esperen por el resultado de la anterior, hasta donde he leído ningún problema por definir async mounted()
y jugar con await
y Promises
, pero ¿qué opináis de esa tercera llamada en bucle?.
Entiendo que si dentro del bucle forEach
de rounds defino el método como asíncrono podré hacer las llamadas correspondientes esperando su ejecución con await
, tal que así:
Array.from(this.rounds).forEach( async round => {
await this.get_competitors_list(round.round_id);
[...]
});
Error, forEach
no va a esperar a que hayan acabado los elementos marcados como tal, simplemente ejecuta y sigue. Así que, leyendo un poco de Iteration protocols veo que en su lugar podemos usar for..of
, que es una versión moderna del "for loop" de forma que, simplemente cambiando forEach y adaptando la sintaxis al nuevo bucle haremos que funcione adecuadamente:
for(let round of this.rounds) {
await this.get_competitors_list(round.round_id);
[...]
}
Y eso es todo, ni más ni menos; una tarde entera de debug y seguir trazas aquí y allá. Todo muy gracioso y divertido.