EcmaScript 6

“Había permanecido en la sombra, esperando, sin prisa, a que alguna fuerza lo trajese de nuevo al mundo de los vivos. Y nada tiene tanta fuerza como una promesa…”

Carlos Ruiz Zafón - El Príncipe de la Niebla

Como hasta ahora no hemos hablado de promesas en este blog, vamos a comenzar haciendo una pequeña introducción a la breve pero apasionante historia de las promesas en JavaScript, para a continuación ver los distintos métodos para trabajar con promesas.

En caso de que os interese el tema, principalmente el caso de async...await que puede llegar a ser confuso en algunos ámbitos, podéis escribir en comentarios las dudas, y puedo preparar un artículo para ampliarlas.

Introducción

En un principio, al trabajar con JavaScript, cuando nos encontrábamos con un código que se debía ejecutar de forma asíncrona se utilizaban callbacks para controlar cuando había terminado la ejecución del código asíncrono. Pondremos en los siguientes ejemplos, el mismo código evolucionando:

function onFileListReceived(fileList) {}
function onFileListFail(errorMessage) {}

fetchFileList(onFileListReceived, onFileListFail);

Con el paso del tiempo, la librería jQuery comenzó a usar lo que llamaban deferreds, un sistema con el que la gestión de las llamadas asíncronas pasa a ser un poco más descriptiva. Para ello se tenía un objeto al que se podían ir enlazando callbacks por cada resultado de la operación asíncrona.

fetchFileList()
 .done(onFileListReceived)
 .fail(onFileListFail);

Con este esquema se paso a tener una estructura muy similar cuando llegaron las promesas al propio JavaScript:

fetchFileList()
  .then(onFileListReceived)
  .catch(onFileListFail);

Cabe destacar que también existe la estructura then() con dos parámetros, en la que el primero funcionaría como callback cuando la promesa termina correctamente, y el segundo, cuando termina de forma errónea.

La siguiente evolución en JavaScript fue la llegada de async...await. Esta estructura ayuda a "leer" el código asíncrono como si fuera síncrono:

try {
  const fileList = await fetchFileList();
  // Realizar las operaciones deseadas
} catch (fileListError) {
  // Código en caso de fallo de la promesa.
}

Métodos del objeto Promise

resolve() y reject()

Estos dos métodos son los más sencillos de utilizar y permiten generar una promesa resuelta (con resolve) o una promesa rechazada con (reject).

function resolveName() {
  return Promise.resolve("John");
} 

function rejectName() {
  return Promise.reject("Error message");

...

// Con esto, resultado tendrá el valor "John"
const name = await resolveName();

try {
  await rejectName();
} catch (promiseError) {
  // promiseError tendrá el valor "Error message";
}

any()

Este método puede recibir varias promesas, y terminará en cuanto la primera de ellas se cumpla. El resto de promesas serán "omitidas".

const firstPromise = new Promise1;
const secondPromise = Promise.reject("Esta no va a funcionar");
const thirdPromise = new Promise2;

const promises = [firstPromise, secondPromise, thirdPromise];

// Esto mostrará en consola: "Promesa a 10ms" pues es la que termina primero
console.log(await Promise.any(promises));

race()

En esta ocasión, el método terminará en cuanto una promesa se cumpla o finalice erróneamente.

const firstPromise = new Promise3;
const secondPromise = Promise.reject("Esta no va a funcionar");
const thirdPromise = new Promise4;

const promises = [firstPromise, secondPromise, thirdPromise];

// Esto mostrará en consola: "Esta no va a funcionar" puesto que termina primero la promesa rechazada
try {
  await Promise.race(promises);
} catch (error) {
  console.log(error);
}

Como resumen de los métodos any() y race(). Tenemos que, con any esperamos a que al menos una promesa termine bien, y si ninguna termina correctamente el flujo finalizará con la última promesa. Con race, sin embargo, el código se espera a que la promesa más rápida termine, ya sea correcta o erróneamente.

all()

Se resuelve cuando terminan todas las promesas correctamente. En caso de que una de ellas falle, la promesa generada por all() será rechazada.

const firstPromise1 = Promise.resolve("first promise");
const secondPromise = Promise.resolve("second promise";
const thirdPromise = new Promise5;

allSettled()

El último de los métodos de Promise, lo que hará es terminar cuando hayan acabado todas las promesas que recibe, ya sea correcta, o erróneamente. Para ello, el resultado será un array con las promesas.

const firstPromise = Promise.resolve("first promise");
const secondPromise = Promise.reject("failed promise");
const promises = [firstPromise, secondPromise];

// Imprimirá en la consola un array con dos promesas, una cumplida y otra rechazada.
// [
//   { status: "fulfilled", value: "first promise" }
//   { status: "rejected", reason: "failed promise" }
// ]
console.log(await Promise.allSettled(promises));

Resumen

MétodoExplicación
resolveGenera una promesa resuelta automáticamente.
rejectGenera una promesa rechazada automáticamente.
anyGenera una promesa que se finaliza en cuanto termina correctamente una de las que recibe.
raceGenera una promesa que finaliza en cuanto termina una de las promesas que recibe, ya sea correcta o erróneamente.
allEspera a que terminen todas las promesas. Si falla una de ellas, la promesa será rechaza.
allSettledEspera a que terminen todas las promesas, independientemente de si terminan correctamente o fallan.

Y con esto terminamos todos los métodos que nos ofrece el objeto Promise. Lo dicho al principio del artículo, si queréis una explicación más completa de como funcionan las promesas en JavaScript dejad un comentario y preparé un artículo más completo para comentarlas.

Para ampliar algo de información sobre las promesas podéis recurrir a los siguientes libros:


  1. resolve) => setTimeout(resolve, 50, "Promesa a 50ms" 

  2. resolve) => setTimeout(resolve, 10, "Promesa a 10ms" 

  3. resolve) => setTimeout(resolve, 50, "Promesa a 50ms" 

  4. resolve) => setTimeout(resolve, 10, "Promesa a 10ms" 

  5. resolve) => { setTimeout(resolve, 100, "third promise"); }); const promises = [firstPromise, secondPromise, thirdPromise]; // Esto mostrará en consola '["first promise", "second promise", "third promise"]'. console.log(await Promise.all(promises 

Comparte este artículo con quien quieras
Clases vs Clases abstractas vs Interfaces
Nueva canción: The Spring is Comming

Leave a Comment

Your email address will not be published. Required fields are marked *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.