Avancé25 min de lecture

Gestion des Erreurs

Apprends à gérer les erreurs d'exécution avec élégance grâce à try/catch/finally, à lancer des erreurs personnalisées et à comprendre les types d'erreurs.

Pourquoi la Gestion des Erreurs ?

Les erreurs d'exécution sont inévitables en programmation. Sans une gestion appropriée, une seule erreur peut planter tout ton programme et laisser les utilisateurs face à une page cassée.

Toutes les erreurs ne sont pas des bugs dans ton code. Beaucoup proviennent de sources externes que tu ne peux pas contrôler :

  • Pannes réseau — appels API qui expirent ou renvoient des erreurs
  • Saisie utilisateur invalide — formats inattendus, champs manquants, données invalides
  • Données manquantes — accès à des propriétés sur null ou undefined
  • Erreurs d'analyse — JSON invalide provenant d'une réponse serveur
  • Différences entre navigateurs — API non disponibles dans tous les navigateurs

La gestion des erreurs permet à ton programme de détecter ces problèmes et de réagir avec élégance au lieu de planter :

javascript
// Sans gestion des erreurs — ça plante !
const data = JSON.parse('invalid json'); // SyntaxError!
console.log('Ceci ne s'exécute jamais');

// Avec gestion des erreurs — récupération élégante
try {
  const data = JSON.parse('invalid json');
} catch (error) {
  console.log('Données invalides, utilisation des valeurs par défaut');
  const data = {};
}
console.log('Le programme continue de s'exécuter');

Une bonne gestion des erreurs améliore l'expérience utilisateur (afficher des messages utiles au lieu d'écrans vides), le débogage (journaliser des informations d'erreur significatives) et la fiabilité (maintenir l'application en marche quand les choses tournent mal).

try / catch / finally

L'instruction try...catch te permet de tenter du code risqué et de gérer toute erreur qui survient :

javascript
try {
  // Code qui pourrait lancer une erreur
  const result = riskyOperation();
  console.log(result);
} catch (error) {
  // Code qui s'exécute si une erreur est lancée
  console.log('Quelque chose s'est mal passé:', error.message);
}

L'objet error dans le bloc catch possède des propriétés utiles :

  • error.message — une description lisible de l'erreur
  • error.name — le type d'erreur (ex : 'TypeError', 'SyntaxError')
  • error.stack — une trace de la pile montrant où l'erreur s'est produite (utile pour le débogage)

Le bloc finally s'exécute quoi qu'il arrive — que le code ait réussi ou échoué. Il est parfait pour les opérations de nettoyage :

javascript
let connection;
try {
  connection = openDatabase();
  const data = connection.query('SELECT * FROM users');
  processData(data);
} catch (error) {
  console.log('Erreur de base de données:', error.message);
} finally {
  // Toujours fermer la connexion, même s'il y a eu une erreur
  if (connection) {
    connection.close();
  }
}

Tu peux aussi imbriquer des blocs try...catch pour une gestion d'erreur plus granulaire :

javascript
try {
  try {
    JSON.parse(input);
  } catch (parseError) {
    console.log('Analyse échouée, tentative alternative...');
    JSON.parse(alternativeInput);
  }
} catch (error) {
  console.log('Toutes les analyses ont échoué:', error.message);
}

Lancer des Erreurs

Tu peux lancer tes propres erreurs en utilisant l'instruction throw. C'est utile pour appliquer des règles de validation et des contrats de fonction :

javascript
function divide(a, b) {
  if (b === 0) {
    throw new Error('Impossible de diviser par zéro');
  }
  return a / b;
}

try {
  const result = divide(10, 0);
} catch (error) {
  console.log(error.message); // 'Impossible de diviser par zéro'
}

JavaScript possède plusieurs types d'erreurs intégrés, chacun signalant un type de problème différent :

  • TypeError — mauvais type : null.property, appel d'une non-fonction
  • ReferenceError — utilisation d'une variable non définie
  • RangeError — valeur hors limites : new Array(-1)
  • SyntaxError — code invalide : JSON.parse('{')
  • URIError — URI mal formée : decodeURI('%')

Tu peux lancer des types d'erreur spécifiques pour plus de clarté :

javascript
function setAge(age) {
  if (typeof age !== 'number') {
    throw new TypeError('L'âge doit être un nombre');
  }
  if (age < 0 || age > 150) {
    throw new RangeError('L'âge doit être entre 0 et 150');
  }
  return age;
}

Tu peux aussi créer des classes d'erreur personnalisées pour ton application :

javascript
class ValidationError extends Error {
  constructor(field, message) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

throw new ValidationError('email', 'Format d'email invalide');

Modèles de Gestion des Erreurs

Voici des modèles pratiques pour gérer les erreurs efficacement :

1. Valider les entrées tôt (clauses de garde) :

javascript
function processUser(user) {
  if (!user) throw new Error('Utilisateur requis');
  if (!user.email) throw new Error('Email requis');
  // ... continuer avec des données valides
}

2. Envelopper les opérations risquées dans try/catch :

javascript
function loadConfig(jsonString) {
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    console.warn('Configuration invalide, utilisation des valeurs par défaut');
    return { theme: 'dark', language: 'en' };
  }
}

3. Ne pas capturer les erreurs que tu ne peux pas gérer — laisse-les remonter vers un gestionnaire de niveau supérieur :

javascript
function readFile(path) {
  // Si ça échoue, laisse l'appelant le gérer
  // Ne capture pas et ne masque pas silencieusement l'erreur
  return fs.readFileSync(path, 'utf8');
}

4. Relancer les erreurs quand tu as besoin de journaliser mais pas de les gérer complètement :

javascript
try {
  processPayment(order);
} catch (error) {
  console.error('Paiement échoué:', error);
  throw error; // relancer pour que l'appelant la gère
}

5. Limites d'erreur — dans des frameworks comme React, tu peux capturer les erreurs de rendu au niveau d'un composant afin qu'un composant cassé ne plante pas toute l'application. Le concept s'applique largement : capture les erreurs aux limites appropriées dans ton application.

Gestion des Erreurs en Action

html
<div id="output"></div>

<script>
  function safeParseJSON(str) {
    try {
      const data = JSON.parse(str);
      return { success: true, data };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }

  // Test avec JSON valide
  const valid = safeParseJSON('{"name": "Alice", "age": 30}');

  // Test avec JSON invalide
  const invalid = safeParseJSON('not valid json');

  const output = document.getElementById('output');
  output.innerHTML = `
    <p><strong>JSON valide:</strong> ${valid.success ? valid.data.name : 'Échoué'}</p>
    <p><strong>JSON invalide:</strong> ${invalid.success ? 'Analysé' : invalid.error}</p>
  `;
</script>

Quand le bloc finally s'exécute-t-il ?

Prêt à pratiquer ?

Crée ton compte gratuit pour accéder à l'éditeur de code interactif, lancer les défis et suivre ta progression.