JavaScript – Gestion des Error / Exception de manière globale

En JavaScript, j’en apprend presque tous les jours, il faut dire que je pars de loin :). En ActionScript, il y a un mécanisme permettant de gérer les exceptions « runtime » de manière globale depuis Flash Player 10.1:

Global Error Handling in AIR 2.0 and Flash 10.1

Bien pratique pour éviter les mauvaises surprises, comme des accès à des objets null non vérifiés. Lorsqu’une exception se produit au sein de l’exécution de la VM Flash Player, votre programme devient instable. Il peut continuer à fonctionner, partiellement, ou pas du tout, c’est assez capricieux, il vaut mieux prévenir l’utilisateur qu’une erreur s’est produite.

Pour ce qui est de l’exécution du JavaScript, c’est à peu près pareil, il arrive que l’exécution se stoppe après une exception. En JavaScript, il est possible de gérer les erreurs de 2 manières:

  • avec un try / catch pour les erreurs pour les exceptions lancée à l’aide d’une instruction « throw »
  • un event handler nommé « onerror » sur window

Pour le premier, c’est assez classique en programmation, je vous passe les détails. En revanche, je ne connaissais pas le second.

Exemple d’utilisation de window.onerror

Un petit exemple:

window.onerror = function(errorMeaage, fileName, lineNumber){
    document.write('Error: ' + errorMeaage);
}

On récupère donc le message d’erreur (venant de l’exception), le nom du fichier JS qui a lancé cette erreur et le numéro de ligne.

Attention, selon les navigateurs et leurs versions, il se peut que vous ne récupériez pas toutes ces informations.

Utilisation de Error::stack

Au delà de cela, il existe aussi une autre technique, il existe aussi une manière d’obtenir la stack d’appel, c’est-à-dire l’enchaînement des fonctions qui a mené à cette erreur. C’est souvent l’information qui est la plus pertinente pour la résolution d’un bug. Cette propriété se nommé « stack » et est présente sur les objets de type error. Voici la documentation officielle:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack

Comme vous le voyez, vous pouvez lancer une erreur et récupérer la stack d’appel complète:

function trace() {
            try {
                throw new Error("myError");
            }
            catch(e) {
                alert(e.stack);
            }
        }

Comme vous pouvez le voir dans la table de compatibilité, cette fonction n’est pas disponible dans IE ni dans certains Safari. En plus de cela, les stacks d’erreurs peuvent être assez sombres.

Utilisation de librairies externes: Tracekit et StackTrace

Pour faire ce travail de compatibilité entre les browser qui gèrent certaines propriétés et d’autres qui n’envoient qu’une partie des informations, il vaut mieux faire confiance à une petite librairie qui va faire le boulot à votre place. Il serait dommage d’avoir des exceptions dans le code qui gère les exceptions, non ? :).

Dans les liens de la page MDN, on trouve 2 librairies externes

TraceKit

https://github.com/csnover/TraceKit

L’API est assez simple et vous permet de vous inscrire à TraceKit pour récupérer les exceptions éventuelles:

TraceKit.report.subscribe(function(stackInfo) { ... })

Derrière, TraceKit va faire le boulot et récupérer un maximum d’informations. Voici à quoi ressemble l’objet stackInfo dans Chrome:

TraceKit est même allé plus loin dans la recherche et est en fait allé chercher en XHR le fichier source JavaScript pour trouver le contexte de la méthode qui n’a pas fonctionné. Dans l’objet stack[0].context, il y a donc les 2 lignes qui entourent l’appel en question. Dans un environnement de production, ces fichiers ne seront pas présents, il est donc peu probable que cela vous serve. On peut voir aussi qu’en environnement de dev, Chrome donne une bonne explication, avec la stack trace et un lien vers le fichier en question à la bonne ligne.

StackTrace.js

https://github.com/eriwen/javascript-stacktrace

StackTrace.js est plus simple et vous permet d’obtenir la stack à un moment donné dans votre code:

if (errorCondition) {
         var trace = printStackTrace();
         //Output however you want!
         alert(trace.join('\n\n'));
    }

Pour vous aider à lire le contenu, il va faire quelques remplacements dans le texte. De la même manière, il essaie aussi de charger le script JS en XHR et de « deviner » d’où vient l’exception, notamment pour les fonctions anonymes difficiles à pister.

Conclusion

Voici quelques pistes pour vous aider à traiter les problèmes d’exception en JavaScript. Le traitement de l’exception récupérée est laissée au bon vouloir du développeur.

Un des meilleurs traitement que j’ai vu est celui  de l’application Flex SpatialKey qui lorsqu’il se passe une exception, alerte l’utilisateur, lui propose de rentrer un message expliquant comment s’est produit le bug (enchaînement des opérations) pendant qu’il s’en souvient encore et l’envoie directement à l’assistance puis vous renvoie directement un numéro de ticket (type JIRA) pour que vous puissiez voir l’avancement de la résolution du problème. Solution originale et productive je trouve :).

2 réflexions au sujet de « JavaScript – Gestion des Error / Exception de manière globale »

  1. lionel

    A savoir aussi, pour ceux qui travaille avec chrome, la possibilité d’insérer le mot clef « debugger » qui fait office de point d’arret lors de l’éxécution du JS.

    Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *