Excepții în lanțurile de promisiuni în JavaScript
Să presupunem că, din anumite motive, promisiunea noastră se finalizează cu o eroare:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
În acest caz, execuția codului va trece imediat
la acel then care are funcția de gestionare a
eroare, sau la primul catch, în funcție
de care este întâlnit mai devreme.
Iată un exemplu al primei situații:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// execuția va trece imediat aici
}
).then(
function(result) {
console.log(result);
}
);
Iată un exemplu al celei de-a doua situații:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// execuția va trece imediat aici
}
).then(
function(result) {
console.log(result);
}
);
Funcția de gestionare are două variante de acțiune:
dacă a gestionat situația excepțională,
poate returna rezultatul prin return
și execuția va continua mai departe în lanț.
Dacă nu a putut gestiona eroarea, poate
fie să nu returneze nimic, fie să arunce o excepție
prin throw. În acest caz, execuția
va trece la următorul interceptator de erori
(în then sau catch - oricare este întâlnit
mai devreme).
De obicei, toate erorile din lanț sunt interceptate
într-un singur loc: la sfârșitul lanțului este plasat
un catch:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// vom ajunge aici în caz de eroare
}
);
În acest caz, excepția poate apărea în promisiunea
în sine, sau poate fi aruncată prin throw
în orice verigă a lanțului:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (totulEsteBine) {
return result + '2';
} else {
throw new Error('eroare'); // trecem la cel mai apropiat interceptator
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// interceptatorul cel mai apropiat
}
);
Rețineți că catch este necesar tocmai pentru
diagnosticarea erorii: este rezolvabilă sau nu.
Dacă eroarea este rezolvabilă, atunci catch ar trebui
să transmită soluția ei următorului then de după el.
Iar dacă nu este rezolvabilă (sau acest catch
pur și simplu nu știe cum să o rezolve), atunci trebuie
fie să nu returnăm nimic, fie să aruncăm o excepție:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (eroareaEsteRezolvabila) {
return 'date'; // trimitem la următorul then
} else {
// nu returnăm nimic sau aruncăm o excepție
}
}
).then(
function(result) {
// aici rezolvăm eroarea
}
);