Promesas en Javascript

Anteriormente si se quería separar o esperar cierto valor que llevaba un complejo proceso de operaciones se separaba en una función y agregabas un callback a esa función. No es malo hacer esto, el problema es la cantidad de callbacks que podemos anidar en nuestro flujo, se verá horrible.

Un callback es una función que se ejecutará en el contexto de otra función.

Toma lo siguiente de referencia, declaramos un ciclo for que cuenta de1 hasta 10. Cuando llege a 5 se ejecuta una función y se hace un proceso con ese resultado, mostrarlo en consola por ejemplo.

La imagen representa cómo cada función ejecuta una función callback y comparte su valor dentro de ese contexto a cada nuevo callback ejecutado.

Callback Hell

Tomando de referencia el mecanismo de compartir el nuevo valor de algo y exponerlo a otra función(callback) podemos simular una promesa. ¿ Cómo la simulamos ?, facil. Llamando una función y pasandole cómo argumentos 2 funciones, onSucess y onError, de este modo mipromesa( onSucess, onError ).

Lo que pasa es que a medida agregas más y más de este tipo de código aportamos al nacimiento de un fenómeno conocido cómo el Callback Hell.

El Callback Hell es hacer docenas de métodos que reciben n callbacks y se anidan de una manera súper, súper fea.

Así:

Ahora si, las Promises

Existe una mejor manera de controlar el flujo de datos y la lógica de tu app. A diferencia del caos y el incremento del callback hell que podría generarse sin Promises además de la incomoda lectura de código, entre otros. Existen las preciosas Promises.

MDN dice: A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason.

— Una Promesa es una función que se ejecuta fuera del ámbito dónde se le llame se puede decir que se agrega a un stack del call stack conocido cómo “micro tasks”.

Las Promises se exponen para ser consumidas con el método .then. Una promesa puede tener uno estos 3 estados:

  • Pending
  • Fulfilled
  • Rejected

En el mundo del frontend vas a pasar la mayoría de tu tiempo consumiendo estás promesas, ya que siempre estarás consumiendo APIs web y de servicios cuando integras a las plataformas.

Haciendo una Promise

Para crear una promesa usamos esta sintaxis: new Promise((resolve, reject))

resolve: Se ejecuta para decir que todo ha ido bien y queremos retornar el valor de nuestra Promise. Al llamar resolve la promise pasará a estado Fulfilled.

reject: Retornar un valor de error y ejecutar el callback en nuestro .catch. Se llamará a reject cuando nuestra promise no retornará lo esperado o que sucedió algo que no debía en el ámbito de nuestra promise. Por defecto al crear una promesa estará en el estado “pending”. Por lo cual esperamos nuestra promesa tenga éxito haciendo el proceso que tenga que hacer o que se rompa y nos ejecute el estado Rejected y su respectivo callback.

Chaining syntax con Promises

Las promesas pueden retornar otra promesa cuando está “se cumple”, por ejemplo siguiendo el siguiente ejemplo:

  const decirHola = new Promise(resolve => resolve(console.log("Hola")));
  const decirAdios = () =>
    new Promise((resolve, reject) => reject(console.log("Nope")));
  const onError = () => console.error("Que sad, borra eso");
  decirHola.then(decirAdios).catch(onError);

Puedes copiar y pegar esto en la consola del navegador y verás que mostrará en este orden:

  • “Hola”
  • “Nope”
  • "Que sad, borra eso" ( Error message )

Un ejemplo más “Técnico”

 function getGithubDataFor(githubProfileName = "") {
    return new Promise((resolve, reject) => {
      const response = fetch(
        `https://api.github.com/users/${githubProfileName}`
      ).then(response => {
        response.json().then(json => {
          const { html_url, company, id, node_id } = json;
          resolve({ html_url, company, id, node_id, date: new Date() });
          // De todo el payload solamente retornamos estas props
        });
      });
    });
  }
  
  // LLamando la función que retorna una Promesa
  getGithubDataFor("octocat").then(obj => {
    console.log({ obj });
    // Mostramos en consola el objeto
  });

El ejemplo consume la API de Github, puedes consultar por un username de Github, en este caso “octocat” y del response se sacan cómo ejemplos datos “importantes” para pintar el frontend, pero.... obviamente en el callback lo que hace es hacer un console.log del objeto.

Lectura recomendada

👋HEY
WANNA READ MORE STUFF ?

Sure, take me there