JavaScript: Bucle asíncrono

viernes, abril 10, 2020
Banner JavaScript

Cuando programamos en JavaScript es común que debamos iterar sobre un array y en cada iteración llevar a cabo una operación que tome un tiempo indeterminado. Entonces podemos requerir esperar a que se ejecuten completamente las instrucciones solicitadas en una iteración para dar paso a la siguiente.



Supongamos que tenemos el siguiente array de personas:

const persons = [{
    name: 'Ana',
    timeout: 2000
}, {
    name: 'Emilia',
    timeout: 1000
 }, {
    name: 'Juan',
    timeout: 500
}];

Luego nos tomaremos el tiempo indicado en la propiedad timeout para saludar a cada persona con la siguiente función:

const sayHello = ({
    name,
    timeout
}) => {
    setTimeout(() => {
        console.log(`Hello ${name}`);
    }, timeout);
}

Lo más habitual que tenemos para iterar y saludar a todas las personas de nuestro array es usar un forEach:

persons.forEach(person => {
    sayHello(person);
});
//Imprime:
//Juan
//Emilia
//Ana

Si ejecutamos el código anterior podemos ver que se ejecuta el saludo en forma desordenada, ya que se hace en orden de quien tiene el timeout más corto de espera. Lo que queremos es que se ejecuten en el orden que tenemos a las personas en el array. Para lograrlo lo primero que debemos que hacer es convertir a sayHello en una función asíncrona envolviendo el setTimeout en un Promise:

const sayHello = ({
    name,
    timeout
}) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Hello ${name}`);
            return resolve();
        }, timeout);
    });
}

Ahora que la función es asíncrona hacemos un pequeño ajuste a nuestro código del forEach agregando async/await:

persons.forEach(async person => {
    await sayHello(person);
});
//Imprime:
//Juan
//Emilia
//Ana

Como podemos ver, seguimos con el mismo resultado ya que forEach no admite ejecución asíncrona dentro de cada iteración por lo cual JavaScript nos presenta otra alternativa usando for (lo envuelvo en una función ya que siempre await se debe ejecutar dentro de una función async):

(async function() {
    for (let person of persons) {
        await sayHello(person);
    }

})();
//Imprime:
//Ana
//Emilia
//Juan

Con el bucle for de JavasScript si se nos permite ejecutar de forma correcta código asíncrono dentro de cada iteración.

También te puede interesar

Cuando navego por los sitios web, mi parte favorita es leer los comentarios. Es por eso que tus comentarios son un complemento valioso para mis entradas. Cualquier duda o aporte no dejes de escribirlo, en breve lo estaré publicando. ¡Gracias!


1 comentarios

  1. Lilian la explicación está fenomenal. No obstante, creo que en la funcion const printHello, querias indicar sayHello.
    Gracias por compartir. Me ha servido tu explicación. Un abrazo

    ResponderBorrar

Lo más reciente

¡Bendiciones para mi Venezuela!

¡Bendiciones para mi Venezuela!