004. Promesas Javascript

Cuando tenemos que estar concatenando una Callback detrás de otra para hacer diferentes tareas, pero que unas dependen de otras, entonces se nos empieza a generar la famosa Callback Hell o pirámide del infierno. Además, si queremos manipular el manejo de errores en la concatenación de funciones, tendríamos que estar haciendo el manejo del error por cada función.

Para resolver el problema de la pirámide del infierno y del manejo de errores, Javascript tiene un mecanismo denominado promesas, las cuales trabajan con dos recursos principales:

  • resolve()
  • reject()

Una promesa la tenemos que ver como un if… else. Si la promesa se cumple se ejecuta el resolve(). Si la promesa falla por el motivo que sea, entonces se ejecuta el reject(). Veamos el funcionamiento de las promesas.

Cuanto tenemos una función que devuelve una promesa, tenemos dos métodos para ir trabajando la sincronía:

  • Método then(): es el siguiente bloque que se va a ejecutar una vez se cumpla la función inicial. Podemos tener tantos métodos then() como necesitemos.
  • Método catch(): Al final de todos los métodos then() tenemos un método catch(), que, como su nombre dice, va a capturar el error resultante del reject().

Las promesas se usan cuando ya tenemos una concatenación de varios procesos asíncronos, de lo contrario es más sencillo utilizar una callback.

Ejm completo

Veamos un ejm completo

Ejm

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Promesas Javascript</title>
  </head>

  <body>
    <h1>Promesas Javascript</h1>

    <script>
      function cuadradoPromise(value) {
        if (typeof value !== "number")
          return Promise.reject(`Error: el valor "${value}" no es un número`);
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve({ value, result: value * value });
          }, 0 || Math.random() * 1000);
        });
      }

      cuadradoPromise(0)
        .then((obj) => {
          console.log(obj);
          console.log("Inicio Promise");
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          return cuadradoPromise(1);
        })
        .then((obj) => {
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          return cuadradoPromise(2);
        })
        .then((obj) => {
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          return cuadradoPromise(3);
        })
        .then((obj) => {
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          return cuadradoPromise(4);
        })
        .then((obj) => {
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          return cuadradoPromise("5");
        })
        .then((obj) => {
          console.log(`Promise: ${obj.value}, ${obj.result}`);
          console.log("Fin Promise");
        })
        .catch((err) => console.log(err));
    </script>
  </body>
</html>

Muchas APIs externas están ya retornando promesas, por ejm, Fetch, que es la forma moderna de hacer Ajax, internamente todo lo trabaja en un objeto de promesa, de tal manera que para ir trabajando los datos que te devuelve una petición Ajax mediante Fetch, vamos a tener que estar utilizando los métodoso then() y catch(). Si utilizamos Firebase para conectarnos a una base de datos en tiempo real, que es un servicio de Google creado con Javascript, los métodos que ofrece para conectarnos a su base de datos o a su servicios de autenticación son promesas, por lo que vamos a estar viendo, sobre todo en código muy moderno, el uso de promesas. Cuando en una API veamos en su documentación que nos va a hacer trabajar con then() y catch() es que está trabajando con promesas.

En el próximo capítulo veremos lo que son las funciones asíncronas, que no vienen a sustituir a las promesas, sino a trabajar juntas.

Scroll al inicio