Las promesas en JavaScript tienen tres estados posibles:
- Pendiente (pending): Es el estado inicial, donde la operación aún no ha sido completada ni fallado.
- Cumplida (fulfilled): Indica que la operación se completó exitsoamente.
- Rechazada (rejected): Indica que la operación ha fallado.
Una vez que una promesa cambia del estado pendiente, puede convertirse en cumplida o rechazada, pero nunca volverá al estado pendiente.
En el estado fulfilled se ejecuta la función de callback pasada a Promise.prototype.then(), mientras que en el estado rejected se ejecuta la función de callback pasada a Promise.prototype.catch() o al segundo parámetro de Promise.prototype.then().
Es importante recordar que una vez que el resultado de una promesa está determinado, este no puede cambiar. Por esta razón, tanto Promise.prototype.then() como Promise.prototype.catch() siempre devuelven un nuevo objeto Promise.
Comportamiento de Promise.prototype.then()
El valor de retorno de then() depende del valor retornado por su función de callback:
1. La función de callback retorna un valor no-Promise o no retorna nada
En este caso, then() devuelve una nueva promesa en estado fulfilled, con el valor retornado por la función de callback.
const promesaInicial = new Promise((resolver, rechazar) => {
resolver('valor inicial');
});
const promesaSecundaria = promesaInicial.then((valor) => {
return "nuevo valor";
});
promesaSecundaria.then((valor) => {
console.log(valor); // "nuevo valor"
});
2. La función de callback lanza una excepción
Si la función de callback lanza un error, then() devuelve una promesa en estado rejected, pasando el error como argumento al siguiente catch().
const promesaInicial = new Promise((resolver, rechazar) => {
resolver('valor inicial');
});
const promesaSecundaria = promesaInicial.then((valor) => {
throw "ocurrió un error";
});
promesaSecundaria.then((valor) => {
console.log("then " + valor); // no se ejecuta
}).catch((error) => {
console.log("catch " + error); // "catch ocurrió un error"
});
3. La función de callback retorna una promesa
Si la función de callback retorna un objeto Promise, then() devuelve una nueva promesa con el mismo estado que la promesa retornada.
const promesaInicial = new Promise((resolver, rechazar) => {
resolver('valor inicial');
});
let promesaInterna;
let promesaSecundaria = promesaInicial.then((valor) => {
promesaInterna = new Promise((resolver, rechazar) => {
resolver('valor interno');
});
return promesaInterna;
});
console.log(promesaSecundaria === promesaInterna); // false
4. La función de callback no se ejecuta
Si la promesa original está en estado rejected y no hay manejador de error, la función de callback de then() no se ejecutará, pero then() aún devolverá una nueva promesa.
const promesaInicial = new Promise((resolver, rechazar) => {
rechazar('error inicial');
});
const promesaSecundaria = promesaInicial.then((valor) => {
console.log("este mensaje no aparecerá");
});
const promesaTercera = promesaSecundaria.then((valor) => {
console.log("then " + valor); // no se ejecuta
});
promesaTercera.catch((error) => {
console.log("catch " + error); // "catch error inicial"
});
Comportamiento de Promise.prototype.catch()
El método catch() funciona de manera similar a then(), pero para manejar estados rechazados. Internamente, catch() utiliza then().
1. La función de callback retorna un valor no-Promise o no retorna nada
Similar a then(), catch() devolverá una promesa en estado fulfilled si la función de callback no retorna una promesa o no lanza un error.
const promesaInicial = new Promise((resolver, rechazar) => {
rechazar('error inicial');
});
const promesaSecundaria = promesaInicial.catch((error) => {
return "error manejado";
});
promesaSecundaria.then((valor) => {
console.log("then " + valor); // "then error manejado"
});
promesaSecundaria.catch((error) => {
console.log("catch " + error); // no se ejecuta
});
2. La función de callback lanza una excepción
Si la función de callback de catch() lanza un error, se devolverá una promesa en estado rejected.
const promesaInicial = new Promise((resolver, rechazar) => {
rechazar('error inicial');
});
const promesaSecundaria = promesaInicial.catch((error) => {
throw "error no manejado";
});
promesaSecundaria.then((valor) => {
console.log("then " + valor); // no se ejecuta
});
promesaSecundaria.catch((error) => {
console.log("catch " + error); // "catch error no manejado"
});
3. La función de callback retorna una promesa
Similar a then(), si la función de callback de catch() retorna una promesa, catch() devolverá una nueva promesa con el mismo estado.
4. La función de callback no se ejecuta
Si la promesa original está en estado fulfilled, la función de callback de catch() no se ejecutará, pero catch() aún devolverá una nueva promesa en estado fulfilled.