Las promesas en Javascript son un tipo de dato, como lo es un
Podemos trabajar con promesas de varias formas. Una de ellas es usar los thennables, donde se utiliza un método llamado .then()
(entonces). Observa la siguiente tabla:
Métodos | Descripción | Más info |
---|---|---|
.then( resolve) | Ejecuta la función cuando la promesa se cumple. | (Este artículo) |
.catch( reject) | Ejecuta la función cuando la promesa se rechaza. | (Este artículo) |
.then( resolve, reject) | Equivale a las 2 anteriores en el mismo .then() . | Ver then() + catch() |
.finally( end) | Ejecuta la función cuando sale de pendiente. | Ver finally() |
Más adelante veremos, que a diferencia del apartado anterior donde se utilizaban solamente funciones callback, en este enfoque se tiende a no anidar promesas, evitando así el famoso Callback Hell, y haciendo el código mucho más legible.
Recordemos que las promesas estarán siempre en un estado de los siguientes:
- 1️⃣
pendiente
(el estado inicial) - 2️⃣
aceptada
(se gestiona a través del.then()
) - 2️⃣
rechazada
(se gestiona a través delcatch()
)
El método .then()
La forma general de consumir una promesa es utilizando el .then()
. Antes de empezar, ten en cuenta que vamos a utilizar la función asíncrona fetch(), que sirve para hacer peticiones y traernos archivos desde una dirección URL concreta:
fetch("/robots.txt"); // Promise { <pending> }
Observa que al ejecutar esa función, en lugar de bloquear la ejecución a la espera de devolver el contenido del archivo que hemos pedido, lo que hace es devolver una promesa
Hasta ahora, solo hemos ejecutado la función, pero no hemos tratado la promesa. Para manejarla, utilizaremos la mencionada función .then()
que existe en cualquier promesa. Dicha función recibe un parámetro, que es la función que se ejecutará cuando la promesa se cumpla:
fetch("/robots.txt").then(function() {
/* Código a realizar cuando se cumpla la promesa */
});
En este caso, la función fetch()
devuelve una promesa que se cumple cuando el navegador obtiene la información solicitada. Cada función asíncrona tiene una condición concreta para que se cumpla la promesa que devuelve, y depende de la implementación del método.
Sin embargo, observa que la función callback no tiene ningún parámetro. Normalmente si que los tiene, y contienen la información que devuelve la promesa cuando se cumple.
Además, observa que he indentado el .then()
para que se lea mejor:
fetch("/robots.txt")
.then(function(response) {
// response: petición de respuesta del recurso solicitado
})
El método .catch()
Además de todo lo explicado, es una buena práctica utilizar también el método .catch()
, que al contrario que el método .then()
, este método ejecutará la función callback pasada por parámetro cuando la promesa se rechaza:
fetch("/robots.txt")
.then(function() {
/* Código a realizar cuando se cumpla la promesa */
})
.catch(function() {
/* Código a realizar cuando se rechaza la promesa */
});
Recuerda que esas funciones callback sólo se ejecutarán en el caso de que se cumpla o rechace la promesa.
Código no bloqueante
Algo muy importante que no se debería pasar por alto, es que el código que hemos ejecutado en los ejemplos anteriores es un código asíncrono no bloqueante.
- Asíncrono: Porque generalmente no se ejecuta de inmediato, sino que tardará en completarse.
- No bloqueante: Porque mientras espera ser ejecutado, no bloquea y continua el resto del programa.
¿Qué significa esto? Significa que cuando llegamos a un .then()
, el sistema no se bloquea, sino que deja la función «pendiente» hasta que se cumpla o rechace la promesa. Mientras esto no ocurra, se continuará procesando y ejecutando el resto del programa.
Observa el siguiente ejemplo:
fetch("/robots.txt")
.then(response => {
console.log("Código asíncrono");
});
console.log("Código síncrono");
Aunque el console.log("Código asíncrono")
figura unas líneas antes del console.log("Código síncrono")
, no se garantiza que se muestre antes, de hecho, normalmente aparecerá después. Esto ocurre porque el console.log()
del interior del .then()
no ocurre inmediatamente, y al no ser bloqueante, se continua con el resto del programa hasta que la promesa de la operación asíncrona se cumpla o rechace, procesando su .then()
o .catch()
, y volviendo a continuar el resto del programa por donde iba.
Las promesas en JavaScript, tanto gestionadas con
then()
como conasync/await
(que veremos más adelante) son no bloqueantes. Sin embargo, conasync/await
, la ejecución dentro de la funciónasync
se "pausa" en los puntos donde se utilizaawait
, aunque el resto del programa sigue siendo no bloqueante.