Il Tao delle promesse
Con un po ‘ più di esperienza e comprensione delle Promesse e delle leggi monadiche che ne regolano l’uso, non avremmo passato così tanto tempo a lavorare sul refactoring di questo pezzo di codice.
In JavaScript, il codice asincrono può essere gestito tramite Promesse, che sono le monadi di continuazione di JavaScript. La cosa più importante in questo caso delle Promesse che sono una monade è che la seguente legge è vera:
Promise.resolve(Promise.resolve(x)) === Promise.resolve(x).
E più importante di quella sopra, questa vale anche per qualsiasi valore x:
Promise.resolve(Promise.reject(x)) === Promise.reject(Promise.resolve(x)) === Promise.reject(x).
Questa regola magica sopra è ciò che mi ha salvato un po ‘ di potere mentale alla fine della giornata. Ciò significava che potevo trattare quegli errori non appena accadevano, all’interno delle proprie funzioni, stando lontano da quella lunga follia a catena. La risposta era sempre lì a fissarmi, non riuscivo a vederlo. Ora capisco, ed è bellissimo.
Questo significa che sono semplicemente il saveApplication funzione come questa, per esempio:
function saveApplication() {
return makeApiCall().catch((err) => Promise.reject('basic'));
}
L’ .blocco catch significa che stiamo gestendo un errore nel passaggio di base del modulo, perché la chiamata saveApplication è correlata al passaggio del modulo chiamato basic. Questo ci ha portato al bel pezzo di codice in basso:
saveApplication()
.then(uploadImages)
.then(saveService)
.then(savePricingInfo)
.then(savePaymentInfo)
.then(gotoMainPage)
.catch((step) => {
setErrorState();
multiStepManager.go(step);
});
Abbiamo dovuto solo cambiare una singola riga della catena Promessa, ora che tutte le funzioni all’interno del .quindi blocks restituisce una Promessa che già rifiuta il passaggio corrispondente.
Ma cosa succede se si verificano altri tipi di errori, che non sono stati gestiti dalle catture interne?
Beh, questo potrebbe essere facilmente risolto implementando tipi di errore personalizzati e separando la valutazione di diversi tipi di errore all’interno del nostro principale .blocco di cattura. Come questo:
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
}
});
In questo caso, il principale .catch block gestisce solo errori di tipo StepError. Altri tipi di errori vengono semplicemente lanciati, non rifiutati, in modo che possano essere gestiti di conseguenza dall’applicazione o dal browser.
Lo stesso principio può e deve essere esteso per gestire tipi di errore specifici, come diversi stati HTTP.