Gestion des erreurs en Javascript & Typescript
Chaque fois qu'une erreur se produit au moment de l'exécution, elle est « jetée » dans Javascript et Typescript, comme c'est le cas dans la plupart des langages de programmation. Les erreurs non gérées entraîneront un plantage de votre application ou service, donc la pire expérience utilisateur possible. Si une erreur se produit, toute progression non enregistrée est perdue et les utilisateurs peuvent potentiellement recommencer un long processus (par exemple, si un utilisateur s'inscrivait sur une plate-forme en fournissant de nombreuses informations). Le résultat est que ces utilisateurs n'utiliseront probablement plus jamais votre produit, car la confiance a été perdue.
Pour gérer de tels cas, une erreur peut être "attrapée". Pour détecter les erreurs dans Javascript et Typescript, vous enveloppez simplement votre code dans un bloc "try", suivi d'un bloc "catch".
async function getData(){
try {
// Call a dummy async 'fetch'-functoin
const result = await fetch();
return { result };
} catch(error) {
return { error };
}
}
// ... later in your code ....
const { result, error } = await getData();
if (error){
// ... handle error case.
}
// Access the results.
Le résultat est que l'erreur ne se propagera pas dans l'ensemble du système, ce qui conduit au plantage, mais sera gérée directement dans le cadre de votre code. L'application ou le service ne plantera pas et une stratégie d'atténuation pour traiter l'erreur peut être appliquée.
Traitement spécial avec le bloc "finally"
En tant qu'étape supplémentaire pour gérer les erreurs, Javascript et Typescript fournissent un mot-clé "finally" supplémentaire. Un tel bloc « finally » exécute tout code dans sa portée après l'exécution du bloc « try » et du bloc « catch » (si une erreur s'est produite).
// This function is absolutely save
// to call. It fetches some data and
// optionally catches a potential error.
//
// After everything's done, a 'finally'
// sends the error to our backend for logs,
// if there was any.
async function getData(){
// In this case, we store the result
// and error in mutable variables,
// then return both.
let result: Result;
let error: Error;
try {
// Call a dummy async 'fetch'-function
result = await fetch();
} catch(e) {
error = e;
} finally {
// After the whole try/catch has been
// processed, we can log the error.
if(error){
await trackErrorInCloud(error);
}
}
return { result, error };
}
// ... same as before ...
Mais attendez, il y a plus ! Saviez-vous que le bloc « finally » est exécuté même si vous retournez un résultat dans le bloc « try » ou « catch » ? Voici un exemple de ce que je veux dire par là.
// Same as the example before, but
// now we directly return from within
// each code block. And this is where
// a side effect can happen.
async function getData(){
try {
const result = await fetch();
return { result };
} catch(error) {
return { error }
} finally {
//
// WATCH OUT!
//
// Just for demo purpose, but this
// line of code will override both
// the return in 'try' as well as 'catch'!
//
// Returning inside of 'finally' is therefore
// dangerous and will lead to hard-to-debug
// issues.
return { finally: true };
}
}
// data === { finally: true }
const data = await getData();
// Here's a better use case for
// finally.
async function getData(){
let error: Error;
try {
const result = await fetch();
return { result };
} catch(e) {
error = e;
return { error }
} finally {
// No return in finally,
// so it's safe to use.
if(error){
await logInCloud()
}
}
}
// if no error === { result: ... }
// if error === { error: ... }
const data = await getData();
Résumé
Comme vous l'avez vu, la gestion des erreurs dans Javascript et Typescript est assez simple et évite un crash complet de votre application. Le traitement spécial du retour des résultats dans les blocs « try » et « catch » est bon à savoir lors de l'utilisation du bloc « finally », mais il ne faut pas en abuser pour éviter d'implémenter votre code dans un style anti-modèle.