Poikkeukset promise-ketjuissa JavaScriptissä
Olkoon jostain syystä promiseemme päätyy virheeseen:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
Tässä tapauksessa koodin suoritus siirtyy välittömästi
siihen then:iin, jossa on virheen käsittelijäfunktio,
tai ensimmäiseen catch:iin, kumpi tulee vastaan
ensin.
Tässä on esimerkki ensimmäisestä tilanteesta:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// suoritus siirtyy välittömästi tänne
}
).then(
function(result) {
console.log(result);
}
);
Tässä on esimerkki toisesta tilanteesta:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// suoritus siirtyy välittömästi tänne
}
).then(
function(result) {
console.log(result);
}
);
Käsittelijäfunktiolla on kaksi vaihtoehtoista toimintatapaa:
jos se selviytyy poikkeustilanteesta,
se voi palauttaa tuloksen return:lla
ja suoritus jatkuu ketjussa eteenpäin.
Jos se ei selviydy virheestä, se voi
joko olla palauttamatta mitään tai heittää poikkeuksen
throw:lla. Tässä tapauksessa suoritus
siirtyy seuraavaan virheen käsittelijään
(then:iin tai catch:iin - kumpi tulee vastaan
ensin).
Yleensä kaikki ketjun virheet käsitellään
yhdessä paikassa: ketjun loppuun sijoitetaan
catch:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// päädymme tänne virheen sattuessa
}
);
Tässä tapauksessa poikkeus voi ilmetä itse
promisessa, tai se voidaan heittää throw:lla
missä tahansa ketjun lenkissä:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (kaikkiHyvin) {
return result + '2';
} else {
throw new Error('virhe'); // siirrytään lähimpään käsittelijään
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// lähin käsittelijä
}
);
Huomioi, että catch:ia tarvitaan nimenomaan
virheen diagnosointia varten: onko se ratkaistavissa vai ei.
Jos virhe on ratkaistavissa, catch:in pitää
lähettää sen ratkaisu seuraavalle then:ille.
Mutta jos se ei ole ratkaistavissa (tai tämä catch
ei yksinkertaisesti tiedä miten se ratkaistaan), meidän pitää
joko olla palauttamatta mitään tai heittää poikkeus:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (virheRatkaistavissa) {
return 'data'; // lähetetään seuraavalle then:ille
} else {
// ei palauteta mitään tai heitetään poikkeus
}
}
).then(
function(result) {
// tässä ratkaistaan virhe
}
);