Excepciones en las cadenas de promesas en JavaScript
Supongamos que por alguna razón nuestra promesa se completa con un error:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
En este caso, la ejecución del código pasará inmediatamente
a aquel then que tenga una función manejadora de errores,
o al primer catch, lo que se encuentre primero.
He aquí un ejemplo de la primera situación:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// la ejecución pasará inmediatamente aquí
}
).then(
function(result) {
console.log(result);
}
);
He aquí un ejemplo de la segunda situación:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// la ejecución pasará inmediatamente aquí
}
).then(
function(result) {
console.log(result);
}
);
La función manejadora tiene dos opciones de acción:
si ha manejado la situación excepcional,
puede devolver un resultado mediante return
y la ejecución continuará más adelante en la cadena.
Si no ha podido manejar el error, puede
o no devolver nada, o lanzar una excepción
mediante throw. En este caso, la ejecución
pasará al siguiente manejador de errores
(en then o catch - lo que se encuentre
primero).
Por regla general, todos los errores de la cadena se interceptan
en un solo lugar: al final de la cadena se coloca
un catch:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// llegaremos aquí en caso de error
}
);
En este caso, la excepción puede ocurrir en la propia
promesa, o ser lanzada mediante throw
en cualquier eslabón de la cadena:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (todoEstáBien) {
return result + '2';
} else {
throw new Error('error'); // pasamos al interceptador más cercano
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// interceptador más cercano
}
);
Tenga en cuenta que catch es necesario precisamente para
diagnosticar el error: si es solucionable o no.
Si el error es solucionable, entonces catch debe
pasar su solución al then que le sigue.
Y si no es solucionable (o este catch
simplemente no sabe cómo resolverlo), entonces debemos
o no devolver nada o lanzar una excepción:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (errorSolucionable) {
return 'datos'; // enviamos al siguiente then
} else {
// no devolvemos nada o lanzamos una excepción
}
}
).then(
function(result) {
// aquí resolvemos el error
}
);