Tao of Promises
med lidt mere erfaring og forståelse af løfter og de monadiske love, der styrer dets anvendelse, ville vi ikke have brugt så meget tid på at arbejde på refactor af dette stykke kode.
i JavaScript kan asynkron kode håndteres via løfter, som er Fortsættelsesmonaderne for JavaScript. Det vigtigste i denne sag om løfter er en monad er, at følgende lov er sandt:
Promise.resolve(Promise.resolve(x)) === Promise.resolve(x).
og vigtigere end den ovenfor, denne gælder også for enhver værdi:
Promise.resolve(Promise.reject(x)) === Promise.reject(Promise.resolve(x)) === Promise.reject(x).
denne magiske regel ovenfor er det, der reddede mig noget tankekraft i slutningen af dagen. Dette betød, at jeg kunne behandle disse fejl, så snart de skete, inde i deres egne funktioner, holde sig væk fra den lange kæde galskab. Svaret var altid der og stirrede på mig, jeg kunne bare ikke se det. Nu ser jeg, og det er smukt.
dette betød, at jeg simpelthen kunne have saveapplicationsfunktionen som denne, for eksempel:
function saveApplication() {
return makeApiCall().catch((err) => Promise.reject('basic'));
}
den .catch block betyder, at vi håndterer en fejl på det grundlæggende trin i formularen, fordi saveApplication-opkaldet er relateret til trinnet i formularen kaldet basic. Dette førte os til det smukke stykke kode nedenunder:
saveApplication()
.then(uploadImages)
.then(saveService)
.then(savePricingInfo)
.then(savePaymentInfo)
.then(gotoMainPage)
.catch((step) => {
setErrorState();
multiStepManager.go(step);
});
Vi var kun nødt til at ændre en enkelt linje i Løftekæden, nu hvor alle funktionerne inde i .derefter returnerer blocks et Løfte, der allerede afviser det tilsvarende trin.
men hvad nu hvis der opstod andre typer fejl, som ikke blev håndteret af de indre fangster?
Nå, det kunne let løses ved at implementere brugerdefinerede fejltyper og adskille evalueringen af forskellige fejltyper inde i vores hoved .fange blok. Sådan her:
function saveApplication() {
return makeApiCall().catch((err) => Promise.reject(new StepError('basic')));
}//
saveApplication()
.then(uploadImages)
.then(saveService)
.then(savePricingInfo)
.then(savePaymentInfo)
.then(gotoMainPage)
.catch((step) => {
if(err instanceof StepError) {
setErrorState();
multiStepManager.go(step);
}
else {
// handle other types of errors
}
});
i dette tilfælde er det vigtigste .catch block håndterer kun fejl af typen StepError. Andre typer fejl kastes simpelthen, ikke afvises, så de kan håndteres i overensstemmelse hermed af applikationen eller bro.sereren.
det samme princip kan og bør udvides til at håndtere specifikke fejltyper, såsom forskellige HTTP-statuser.