Promises All – Typescript

El poder trabajar con procesos asíncrono (Async) es una de las cosas mas usadas hoy día en el desarrollo, no importa si es algo web o un api con node, o incluso una llamada a un backend desde una aplicación móvil con React-Native las promesas son útiles y nos ayudan a encadenar nuestro código para que funcione de forma magnifica sin tener que estorbar en el main thread de nuestra aplicación.

Para todo eso,  Javascript tiene una API bastante fácil de usar y flexible al mismo tiempo «Promises», el cual consta de varios métodos, podríamos pasarnos la vida entera solo con Then y Catch pero podríamos sacarle mas provecho aun si conocemos las funciones de Race o All

Proposito

Primero lo primero, el propósito general de Las promesas es ejecutar código pero el código no es tan importante como que las vistas este actualizadas, así que delegamos esa ejecución a un segundo plano y esta sera ejecutada justamente luego que el bloque de código termine.

Otra cosa interesante con las promesas es que llegaron en su momento para evitar tener que usar tantos callbacks en nuestro código, tanto en web development como trabajar con node se utilizaban muchos callbacks y al final el código quedaba muy mal por lo que se crearon las promesas para incluso poder crear una cadena de ejecución.

const funcion1 = () => {
    let promesa = new Promise((resolve, reject) => {
        resolve("Primera funcion")
    });
    return promesa;
}

const funcion2 = () => {
    let promesa = new Promise((resolve, reject) => {
        resolve("Segunda funcion")
    });
    return promesa;
}

funcion1()
  .then((resultado) => {
    console.log("Resultado", resultado);
  })
  .catch((error) => {
    console.log("Error capturado", error);
  });

funcion1()
  .then((resultado) => {
    console.log("Resultado", resultado);

    return funcion2();
  })
  .then((resultado) => {
    console.log("Resultado", resultado);

    return funcion2();
  })
  .catch((error) => {
    console.log("Error capturado", error);
  });

Promise – All

Digamos que necesitamos realizar varias tareas relacionadas con el mismo tipo de acción pero son diferentes, en vez de crear un for-loop y ejecutar todas esas tareas (Lo cual no es buena idea) podríamos utilizar promises y crear una promesa para cada tarea y Utilizar la función estática de la clase Promise y llamarlas a todas y una vez están todas completas nos retornara una lista de resultados.

Tenemos una función que realiza una función «pesada» y queremos realizar la misma función varias veces pero con un parámetros diferente. podríamos tener algo como lo siguiente:

const funcionPesada = (parametro) => {
  const promesa = new Promise((resolve, reject) => {
    if (Math.ceil(Math.random() * 100) % 2 == 0) {
      resolve(`Exito ${parametro}`);
    } else {
      reject(`Tarea fallida ${parametro}`)
    }
  });
  return promesa;
}

funcionPesada(1)
.then((resultado) => {
  console.log("Valor", resultado);
}).catch((error) => {
  console.log("Error", error);
});

Este código funcionaria bien y estaría dando una respuesta correcta, lo único malo es que si alguna función se ejecuta bien nunca lo sabremos por que nunca se llamara el método then de la promesa por que sucedió un error.

const parametros = [1, 2, 3, 4, 5];

const promesas = parametros.map((parametro) => {
  return funcionPesada(parametro)
});

Promise.all(promesas)
  .then((resultados) => {
    console.log("Resultado", resultados);
  })
  .catch((error) => {
    console.log("Error", error);
  });

Una solución simple para esto seria que en vez de lanzar un error cuando una promesa falle podríamos nosotros mismo retorna un valor no deseado y validar por ese valor.

const funcionPesada = (parametro) => {
  const promesa = new Promise((resolve, reject) => {
    if (Math.ceil(Math.random() * 100) % 2 == 0) {
      resolve({parametro, exito: true});
    } else {
      resolve({parametro, exito: false});
    }
  });
  return promesa;
}

const parametros = [1, 2, 3, 4, 5];

const promesas = parametros.map((parametro) => {
  return funcionPesada(parametro)
});

Promise.all(promesas)
  .then((resultados) => {
    console.log("Resultado", resultados);
  })
  .catch((error) => {
    console.log("Error", error);
  });

Con una modificación a nuestra función «pesada» podríamos ejecutar todas las funciones y recibir el resultado en nuestra función «then» y ya luego de ahí proceder.

Referencias

Promesas
Promesas – All
Código Fuente