Promesas en serie y en paralelo en JavaScript

Publicado el 02.04.2022 a las 13:21

Promesas en serie y en paralelo en JavaScript

Promesas en serie y en paralelo en JavaScript

驴C贸mo y cuando debo de usar promesas en serie o en paralelo? 馃


Esta semana me he encontrado con un problema 馃槮 en uno de mis productos SaaS y era que una funci贸n en Firebase funtions a veces se ejecutaba por completo y otras no.


La funci贸n siempre comenzaba y terminaba, pero el contenido de la funci贸n a veces se ejecutaba y a veces no.


El problema era que todo el c贸digo dentro de la funci贸n era as铆ncrono, entonces, si el c贸digo de la funci贸n se demoraba mucho en ejecutar Firebase lo mataba porque no era consciente de que hab铆a instrucciones por ejecutar.


Como te estar谩 imaginando, la soluci贸n al problema pasaba por convertir mi c贸digo as铆ncrono en s铆ncrono.

Con async/await es facil铆simo, pero hasta ahora, siempre hab铆a necesitado ejecutar una promesa tras otra porque necesitaba la respuesta de la primera para ejecutar la segunda.


En esta ocasi贸n no era as铆, por lo que decid铆 investigar por la ejecuci贸n de promesas en paralelo (siempre obsesionado con optimizar mi c贸digo y los recursos).

驴Cu谩l era el caso pr谩ctivo?

Tengo un listado de clientes de un producto SaaS en un array, y tengo que consultar para cada uno de los clientes en la base de datos si sigue vigente su subscripci贸n.

Para ello uso una funci贸n Cron Job (puedes conocer m谩s acerca de esas funciones aqu铆) que cada hora ejecuta mi c贸digo.

Como entender谩s no necesito esperar a terminar de leer el primer cliente para comenzar al leer el siguiente, por lo que podr铆a hacer la lectura de los clientes en paralelo ahorrando tiempo, ya que las funciones de Firebase Functions est谩n limitadas a 60".


Pues bien, dicho todo esto te voy a explicar qu茅 son y c贸mo usar las promesas en serie y en paralelo 馃搵

Usar promesas en serie o secunciales 馃殑馃殐馃殐馃殐

Las promesas en serie se utilizan cuando necesitas los datos de la respuesta de la primera promesa para poder ejecutar la segunda promesa.


Imagina que quieres obtener un listado de los nombres de tus repositorios de GitHub, tendr铆as que hacer dos peticiones HTTP, la primera obtener tu perfil de GitHub donde encontrar谩s el endpoint de tus repositorios y a continuaci贸n hacer la petici贸n HTTP a dicho endpoint.


En ese caso tienes que esperar a la respuesta de la primera petici贸n HTTP para poder ejectuar la segunda petici贸n.


Al c贸digo

  fetch("https://api.github.com/users/fjmduran/")
  .then( githubProfile => githubProfile.repos_url )
  .then( reposList => console.log(reposList) ) //Aqu铆 encontrar谩s tus repositorios como un array de objetos JSON
  

Promesas en paralelo

Las promesas en paralelo se usan cuando no necesitas esperar la respuesta de una promesa para ejecutar la siguiente.


Tengo un documento donde un campo es un array con los identificadores de los clientes activos de un producto SaaS.

Teniendo ese array, lo que hago en una Firebase Functions es recorrerlo y hacer la consulta de cada identificador para traer todos los datos del cliente en cuesti贸n. Como comprender谩s no necesito que se haga de forma secuencial, si no que para optimizar los recursos de la Firebase Functions lo que hago es consultar los clientes en paralelo para que la funci贸n dure lo menos posible.

Al c贸digo

  const idCustomers = ["idCustomer1", "idCustomer2",...];
  const promisesCustomers=[];
  for(const idCustomer of idCustomers){
    const promise = admin
      .firestore()
      .collection(`/customers`)
      .doc(`${court.idCourt}`)
      .get();
      promisesCustomers.push(promise);
  }
  await Promise.all(promisesCustomers)
  .then((async (responds) => {
    for (const respond of responds) {
      if (!respond.exists) {
        console.log('No se ha encontrado el cliente');
        return;
      }
      const customer: CustomerInterface = respond.data();
      await checkCustomerValid(customer);
    }        
  })) 
  .catch((err) => {
    console.log('Error en la promesa', err);
  });
  

Aclarando las promesas en paralelo con un ejemplo t铆pico 馃巵

    Imagina que tenemos tres promesas:
  1. const p1 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, "one"); });
  2. const p2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, "two"); });
  3. const p3 = new Promise((resolve, reject) => { setTimeout(resolve, 2000, "three"); });

Si las ejecutamos en paralelo ser铆a:

  Promise.all([p1, p2, p3])
  .then(values => { console.log(values); }, reason => { console.log(reason) });  
  

La salida por consola ser谩 one, three, two y se ejecutar谩 todo en 5 segundos


Si hicieramos el consumo de promesas en serie o secuencial se demorar铆a todo 8 segundos.


Hasta luego 馃枛

Servicios

Software

IoT

Digitalizaci贸n

Aplicaciones m贸viles

Consultor铆a

fjmduran.com v0.2.2