Introduction : Pourquoi la gestion des erreurs est le fondement d'un code fiable
Toute application fonctionnant sur Node.js rencontre tôt ou tard des situations exceptionnelles : saisie utilisateur incorrecte, panne réseau, fichier manquant sur le disque ou données incorrectes provenant de la base de données. Sans une gestion appropriée des erreurs, ces situations entraînent un crash du serveur, une fuite mémoire ou un comportement indéfini. En JavaScript, en particulier dans l'environnement Node.js, le mécanisme try/catch est un outil fondamental pour construire des systèmes tolérants aux pannes. Dans cet article, nous aborderons non seulement le try/catch classique, mais aussi des techniques avancées : les classes d'erreurs personnalisées, le travail avec les promesses et les fonctions asynchrones, ainsi que les meilleures pratiques de journalisation.
Les bases : les blocs try, catch et finally
La syntaxe de base de la gestion des erreurs en JavaScript est la suivante :
try { // Code qui peut lever une exception const data = JSON.parse('{"name": "Node.js"}'); console.log(data.name);} catch (error) { // Gestion de l'erreur console.error('Une erreur est survenue :', error.message);} finally { // Code qui s'exécutera dans tous les cas console.log('Bloc finally exécuté');}Comment cela fonctionne :
try— contient le code potentiellement dangereux.catch— intercepte l'exception si elle se produit. Le paramètreerrorreçoit l'objet d'erreur.finally— s'exécute toujours, qu'il y ait eu une erreur ou non. Idéal pour fermer des fichiers, libérer des ressources ou finaliser des transactions.
Il est important de se rappeler : finally s'exécute même après un return dans le bloc try ou catch.
Types d'erreurs en JavaScript
Les constructeurs d'erreurs intégrés aident à classer plus précisément les exceptions :
Error— classe de base pour toutes les erreurs.SyntaxError— erreur de syntaxe (par exemple, JSON incorrect).TypeError— type de données incorrect (par exemple, appel d'une non-fonction).ReferenceError— référence à une variable inexistante.RangeError— dépassement des limites autorisées (par exemple, récursion).
Exemple de gestion de différents types :
try { const obj = null; console.log(obj.property); // TypeError} catch (err) { if (err instanceof TypeError) { console.log('Erreur de type :', err.message); } else if (err instanceof ReferenceError) { console.log('Variable non trouvée'); } else { console.log('Erreur inconnue :', err); }}Génération de vos propres erreurs : l'opérateur throw
Il est parfois nécessaire d'indiquer explicitement qu'une situation exceptionnelle s'est produite dans le programme. Pour cela, on utilise l'opérateur throw. Il peut lancer n'importe quoi : une chaîne, un nombre, un objet, mais il est préférable d'utiliser une instance de la classe Error ou de ses descendants.
function divide(a, b) { if (b === 0) { throw new Error('La division par zéro est interdite'); } if (typeof a !== 'number' || typeof b !== 'number') { throw new TypeError('Les arguments doivent être des nombres'); } return a / b;}
try { const result = divide(10, 0); console.log(result);} catch (err) { console.error(err.name + ': ' + err.message);}Pourquoi est-il préférable de lancer une Error plutôt qu'une chaîne ? L'objet Error contient la pile d'appels (stack), ce qui est crucial pour le débogage dans Node.js. Une chaîne ne fournira pas cette information.
Création de classes d'erreurs personnalisées
Dans les projets réels (par exemple, un serveur web avec Express), il est pratique d'avoir ses propres types d'erreurs pour différentes situations : ValidationError, NotFoundError, DatabaseError. Cela simplifie la gestion centralisée.
class ValidationError extends Error {