Undantag i kedjor av promises i JavaScript
Låt oss av någon anledning anta att vårt promise avslutas med ett fel:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
I detta fall kommer kodkörningen omedelbart att gå
till den then där det finns en felhanteringsfunktion,
eller till den första catch, beroende på
vad som möts först.
Här är ett exempel på den första situationen:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// körningen går omedelbart hit
}
).then(
function(result) {
console.log(result);
}
);
Här är ett exempel på den andra situationen:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// körningen går omedelbart hit
}
).then(
function(result) {
console.log(result);
}
);
Felhanteringsfunktionen har två åtgärdsalternativ:
om den hanterade undantagssituationen,
kan den returnera ett resultat via return
och körningen kommer att fortsätta längre ned i kedjan.
Om den däremot inte kunde hantera felet, kan den
antingen inte returnera något, eller kasta ett undantag
via throw. I detta fall kommer körningen
att gå till nästa felavfångare
(i then eller catch - beroende på vad som möts
först).
Som regel fångas alla fel i kedjan upp
på ett ställe: en catch placeras
i slutet av kedjan:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// vi hamnar här vid ett fel
}
);
Samtidigt kan undantaget uppstå i själva
promiset, eller kastas via throw
i vilken länk som helst i kedjan:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (alltBra) {
return result + '2';
} else {
throw new Error('error'); // går till närmaste avfångare
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// närmaste avfångare
}
);
Tänk på att catch behövs just för
att diagnostisera felet: är det lösbart eller inte.
Om felet är lösbart, bör catch
skicka dess lösning till nästa then efter sig.
Och om det inte är lösbart (eller denna catch
helt enkelt inte vet hur man löser det), så bör vi
antingen inte returnera något eller kasta ett undantag:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (felLösbart) {
return 'data'; // skickar till nästa then
} else {
// returnerar ingenting eller kastar undantag
}
}
).then(
function(result) {
// här löser vi felet
}
);