Gestion des erreurs JavaScript avec try…catch
Apprenez la gestion des erreurs JavaScript avec try, catch, finally et throw. Couvre l'objet Error, les types d'erreurs intégrés, le rethrowing et les erreurs asynchrones.
Maîtriser la gestion des erreurs en JavaScript avec Try...Catch
Gérer les erreurs efficacement est essentiel pour créer des applications robustes en JavaScript. Lorsque quelque chose se passe mal à l'exécution — un appel réseau échoue, du JSON est malformé, une variable vaut undefined — JavaScript lève une exception. Sans gestion, cette exception arrête votre script. Cet article couvre l'instruction try...catch, la clause finally, l'opérateur throw, l'objet Error et ses sous-types intégrés, le rethrowing, ainsi que la limitation importante selon laquelle un try...catch synchrone ne peut pas attraper les erreurs levées dans des callbacks asynchrones.
Comprendre Try...Catch en JavaScript
L'instruction try...catch est un outil pour gérer les exceptions — des erreurs survenant pendant l'exécution du programme. Elle vous permet de traiter ces exceptions de façon élégante au lieu de laisser tout le script planter.
Le mécanisme comporte deux blocs :
try— le code qui pourrait lever une exception. JavaScript l'exécute normalement.catch (error)— s'exécute uniquement si quelque chose dans le bloctrylève une exception. La valeur levée est passée en paramètre sous le nomerror.
Si aucune erreur ne se produit, le bloc catch est entièrement ignoré. Si une erreur survient, l'exécution saute immédiatement au catch — le reste du bloc try n'est pas exécuté.
Syntaxe de base de Try...Catch
Voici un exemple simple illustrant la structure de base de try...catch :
Dans cet exemple, toute erreur survenant dans le bloc try est attrapée par le bloc catch, où elle peut être gérée sans provoquer le plantage du script.
Lever vos propres erreurs avec throw
L'opérateur throw génère une exception. Vous pouvez lever n'importe quelle valeur, mais la convention — et la seule chose à faire en pratique — est de lever un objet Error (ou une instance de l'un de ses sous-types). Cela vous fournit automatiquement un message utile et une trace de pile (stack).
Évitez throw 'une chaîne' ou throw 42. Une string levée n'a ni message, ni name, ni stack, de sorte que les appelants qui s'attendent à un objet Error (comme la plupart du code) se comporteront incorrectement. Pour les erreurs métier avec des champs supplémentaires, définissez votre propre classe — voir erreurs personnalisées, étendre Error.
L'objet Error
Lorsque vous faites new Error(message), vous obtenez un objet avec trois propriétés couramment utilisées :
name— le type d'erreur, par ex."Error","TypeError","SyntaxError".message— la description lisible que vous avez passée au constructeur.stack— une string avec la pile d'appels au moment où l'erreur a été créée (non standard mais prise en charge par tous les moteurs majeurs ; excellente pour le débogage, pas pour le flux de contrôle).
Types d'erreurs intégrés
JavaScript embarque plusieurs sous-classes d'Error que le moteur lève automatiquement. Les connaître vous aide à écrire une logique catch précise :
| Type | Levé quand |
|---|---|
SyntaxError | Le code ou les données sont malformés, par ex. JSON.parse() sur du JSON invalide. |
TypeError | Une valeur n'est pas du type attendu, par ex. appeler une non-fonction ou lire une propriété de undefined. |
ReferenceError | Une variable qui n'existe pas est référencée. |
RangeError | Une valeur est en dehors de sa plage autorisée, par ex. une longueur de tableau invalide. |
URIError | decodeURIComponent() ou une fonction similaire reçoit une URI malformée. |
EvalError | Historique ; rarement levé par les moteurs modernes. |
Chacun d'eux a name défini selon son type, vous pouvez donc brancher sur instanceof :
Gérer des erreurs spécifiques
Vous pouvez également gérer des types d'erreurs spécifiques en examinant l'objet erreur :
Cet exemple gère spécifiquement la SyntaxError pouvant survenir lors du parsing JSON. Si l'erreur attrapée est une instance de SyntaxError, elle est gérée en journalisant un message spécifique. Sinon, l'erreur est relancée, potentiellement pour être attrapée par un gestionnaire d'erreurs de niveau supérieur ou pour faire planter le programme, indiquant ainsi un scénario d'erreur non gérée.
Relancer des erreurs (Rethrowing)
Un bloc catch attrape toutes les erreurs de son try, y compris celles que vous ne savez pas gérer. Le modèle recommandé est : inspecter l'erreur, gérer les cas que vous comprenez, et relancer tout le reste afin qu'il se propage vers un gestionnaire externe. Avaler silencieusement des erreurs inconnues dissimule de vrais bugs.
Liaison catch optionnelle
Si vous n'avez pas besoin de la valeur d'erreur, vous pouvez omettre entièrement la liaison (ES2019+). Cela est utile lorsque le simple fait que quelque chose a échoué est tout ce qui vous importe :
Utiliser Finally
La clause finally s'exécute après les blocs try et catch, qu'une exception ait été levée ou non. Elle est utile pour libérer des ressources ou effectuer des tâches de nettoyage, indépendamment du résultat du try...catch :
Cela garantit que le message "Finally block executed" est journalisé qu'une erreur se produise ou non, montrant comment finally peut être utilisé pour effectuer des actions de nettoyage nécessaires.
Exemples réels de requêtes API
Utiliser l'API JSONPlaceholder est un excellent moyen de pratiquer la gestion de données réelles en JavaScript, notamment lors de requêtes asynchrones et de la gestion des erreurs potentielles qui peuvent survenir lors de ces opérations. Voici quelques exemples du monde réel utilisant l'API JSONPlaceholder, qui fournit de fausses données REST en ligne pour tester et prototyper.
Exemple 1 : Récupérer des publications et gérer les erreurs
Dans cet exemple, nous récupérons des publications depuis l'API JSONPlaceholder en utilisant fetch et gérons les éventuelles erreurs réseau ou problèmes avec la réponse de l'API :
Ce script effectue une requête HTTP pour récupérer un seul élément todo. Il vérifie si la réponse est réussie (c'est-à-dire HTTP status 200-299). Sinon, il lève une erreur avec le statut de la réponse. Toutes les erreurs, qu'elles proviennent de problèmes réseau ou de l'instruction throw, sont attrapées dans le bloc catch et journalisées. Le bloc finally s'exécute quel que soit le résultat, garantissant que tout nettoyage ou opération finale nécessaire est effectué.
Exemple 2 : Envoyer des données et gérer les exceptions
Ici, nous montrons comment envoyer des données au serveur avec la méthode POST et gérer les exceptions de manière appropriée :
Dans ce script, nous envoyons une nouvelle publication au serveur. La fonction fetch est utilisée avec la méthode POST, incluant des en-têtes et un corps JSON sérialisé. Si la réponse du serveur indique un échec (statut HTTP non-2xx), une erreur est levée, puis attrapée et gérée dans le bloc catch. Quel que soit le succès ou l'échec, le bloc finally garantit que l'opération est marquée comme terminée.
Exemple 3 : Provoquer et gérer délibérément une erreur
Cet exemple demande intentionnellement un identifiant d'utilisateur qui n'existe pas dans l'API JSONPlaceholder, déclenchant une erreur 404 Not Found, que nous allons attraper et gérer.
Comment fonctionne cet exemple
- Point de terminaison API invalide : La fonction
fetchest appelée avec une URL contenant un identifiant d'utilisateur invalide (99999). Étant donné que JSONPlaceholder ne dispose généralement pas d'un utilisateur à cet index, l'API retournera une erreur 404. - Vérification de la validité de la réponse : Le code vérifie si le statut de la réponse n'est pas dans la plage de succès (200-299). L'identifiant d'utilisateur étant invalide, la réponse API sera probablement 404, déclenchant notre gestion d'erreur dans le test
if (!response.ok). - Levée de l'erreur : Puisque la réponse n'est pas OK, une erreur est levée avec un message incluant le statut HTTP, qui dans ce cas indiquera une erreur 404 Not Found.
- Bloc Catch : Le bloc catch capture l'erreur levée et journalise un message spécifique via
console.log. Cela fournit un retour clair sur ce qui s'est mal passé. - Bloc Finally : Ce bloc est utilisé pour le nettoyage ou les instructions finales, indiquant la fin de la tentative, quel qu'en soit le résultat.
Pourquoi Try...Catch ne peut pas attraper les erreurs de callbacks asynchrones
C'est le problème le plus courant avec try...catch. L'instruction est synchrone : elle n'attrape que les erreurs levées pendant que le bloc try est en cours d'exécution. Lorsque vous planifiez un callback avec setTimeout, un écouteur d'événements, ou une promesse non attendue, le callback s'exécute plus tard — après que le try...catch a déjà terminé et que la pile d'appels est vide. À ce stade, il n'y a plus de try environnant pour attraper quoi que ce soit.
Pour gérer l'erreur, le try...catch doit se trouver à l'intérieur du callback, là où l'erreur est réellement levée :
La même règle explique pourquoi try...catch fonctionne avec async/await mais pas avec les promesses nues. await met en pause la fonction et la reprend dans le même flux logique, de sorte qu'une promesse rejetée se manifeste comme une erreur levée que votre try peut attraper. Une promesse que vous n'awaitez pas se règle indépendamment et contourne complètement le try environnant — vous devez utiliser .catch() à la place.
Pour une couverture approfondie de la gestion des erreurs asynchrones, voir Gestion des erreurs avec les promesses et async/await.
Conclusion
Une gestion efficace des erreurs en JavaScript est essentielle pour développer des applications de haute qualité et résilientes. Utiliser try...catch vous permet de gérer élégamment les erreurs synchrones et les rejets awaités tout en conservant le contrôle du flux applicatif. Levez des objets Error (jamais des strings nues), branchez sur les types intégrés comme TypeError et SyntaxError, relancez ce que vous ne pouvez pas gérer, et n'oubliez pas la limitation asynchrone : les erreurs dans les callbacks et les promesses non attendues nécessitent leur propre gestion.
Sujets connexes
- Erreurs personnalisées, étendre Error — définissez vos propres classes d'erreurs.
- Gestion des erreurs avec les promesses —
.catch()et le flux de rejet. - Async/await —
try...catchavec du code asynchrone. - Travailler avec JSON —
JSON.parseet laSyntaxErrorqu'il peut lever.