Quelles sont les meilleures pratiques pour la gestion des erreurs JavaScript?

137

Je cherche à commencer à faire mon JavaScript un peu plus la preuve d'erreur, et je trouve beaucoup de documentation sur l' utilisation try, catch, finallyet throw, mais je ne suis pas trouver une tonne de conseils d'experts sur quand et où jeter des erreurs.

  • Chaque morceau de code doit-il être enveloppé dans un try / catch?
  • Y a-t-il plus de conseils comme celui-ci sur le moment où les erreurs doivent être détectées?
  • Y a-t-il des inconvénients à générer des erreurs au lieu de voir le code échouer silencieusement en production?
  • Cela a été abordé sur SO en ce qui concerne les implémentations, mais les erreurs JS de journalisation du serveur sont-elles une stratégie efficace?
  • Y a-t-il autre chose que je devrais savoir concernant les erreurs de piégeage dans mon application?

Je suis également tout à fait partisan d'entendre des livres qui contiennent de bons chapitres ou des explications détaillées sur la gestion des erreurs. Un JavaScript éloquent aborde la question, mais n'est pas très normatif ou d'opinion sur le problème.

Merci pour tout conseil que vous pouvez donner!

Joshua Cody
la source
Cela dépend sûrement de la façon dont vous échouez si quelque chose ne va pas et du volume de messages d'erreur possibles. Vous ne voulez pas échouer car votre répertoire de journalisation des erreurs est plein maintenant, n'est-ce pas? - Avez-vous regardé ici du tout? stackoverflow.com/search?q=error+logging+javascript
mplungjan
@mplungjan - J'ai parcouru les réponses, mais peu de choses semblaient canoniques, et les recherches sur la gestion des erreurs Javascript / les meilleures pratiques d'exception n'ont rien révélé, alors j'ai pensé qu'il pourrait être utile d'essayer de solliciter des pensées condensées, à la fois pour mon propre compréhension et futurs chercheurs. Peut-être s'agit-il d'un sujet où la prescription des meilleures pratiques n'est pas aussi possible, mais chaque situation est très unique?
Joshua Cody
1
"Chaque morceau de code doit-il être enveloppé dans un try / catch?" Bien sûr que non. Il y a beaucoup de code dont vous savez qu'il fonctionnera toujours (en supposant que vous le testiez, bien sûr, mais le but d'essayer / attraper n'est pas d'attraper ou de passer sous silence les erreurs de codage). N'enveloppez que du code qui peut échouer de temps en temps en raison de quelque chose hors de son contrôle, généralement des choses comme l'accès aux ressources, etc. Remarque: certaines choses qui peuvent échouer ont une gestion des erreurs intégrée, par exemple, je ne prendrais pas la peine de coder Ajax à partir de zéro lorsque il existe de nombreuses bibliothèques qui le font, qui gèrent les problèmes entre navigateurs et vous permettent de spécifier une fonction de gestionnaire d'erreurs.
nnnnnn
1
C'est une bonne question Josh, +1. Beaucoup de conseils syntaxiques, mais comme vous le dites, c'est la partie la plus facile. Il est abordé dans la réponse à cette question ( stackoverflow.com/questions/2825427/… ) où il est expliqué que les exceptions ne sont pas aussi couramment utilisées dans JS et les raisons sont données.
whitneyland

Réponses:

63

Un ensemble extrêmement intéressant de diapositives sur la gestion des erreurs JavaScript d'entreprise est disponible à l' adresse http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

En bref, il résume:

  1. Supposons que votre code échouera
  2. Consigner les erreurs sur le serveur
  3. Vous, et non le navigateur, gérez les erreurs
  4. Identifier où les erreurs peuvent survenir
  5. Lancez vos propres erreurs
  6. Distinguer les erreurs fatales des erreurs non fatales
  7. Fournir un mode de débogage

Les diapositives sont beaucoup plus détaillées et vous donneront probablement une direction.

METTRE À JOUR

La présentation mentionnée ci-dessus peut être trouvée ici: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation

cdmdotnet
la source
24
Le lien devhands est rompu.
Ryan Gates
7
À ceux qui liront ceci en 2017, je dirais que vous n'obtiendrez pas beaucoup de valeur des diapositives - ce résumé vous donne 90% des informations. Ce sont toujours des informations précieuses. À votre santé!
Philippe Hebert
29

Nicholas Zakas de Yahoo! Fame a fait une conférence sur la gestion des erreurs d'entreprise ( diapositives ) à Ajax Experience 2008, dans laquelle il a proposé quelque chose comme ceci:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

Un an plus tard, Nicholas Zakas a publié une mise à jour sur son blog qui comprenait un modèle intelligent pour injecter automatiquement du code de gestion des erreurs sur votre environnement de production (en utilisant une programmation orientée aspect).

Lorsque vous démarrez la journalisation des appels window.error, vous remarquerez deux choses:

  1. Si votre site est assez complexe, vous allez enregistrer de nombreuses erreurs
  2. Vous verrez un tas de messages inutiles "window.error dans undefined: 0"

Réduire le torrent des entrées de journal est aussi simple que de tester la gravité et / ou un nombre aléatoire avant de se connecter au serveur:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

La gestion des erreurs inutiles "window.error in undefined: 0" dépend de l'architecture de votre site, mais vous pouvez essayer d'identifier tous les appels Ajax et de lancer une exception en cas d'échec (renvoyant éventuellement une trace de pile en utilisant stacktrace.js ).

Jens Roland
la source
67
Je sais que c'est une vieille question, mais suggérer d'ignorer au hasard certaines erreurs est l'une des pires idées que j'aie jamais entendues.
jbabey
26
@jbabey: Pour un petit site, vous avez raison, mais si vous exécutez un grand site avec 100 000 ou des millions d'utilisateurs, vous n'avez vraiment pas besoin d'inonder vos serveurs (ou Internet) de demandes de journalisation redondantes. Sur un système suffisamment grand, chaque erreur réelle se produira des dizaines de milliers de fois par jour, donc cette forme de limitation fonctionne très bien. L'idée est effectivement mise en œuvre sur Facebook.
Jens Roland
1
La journalisation des erreurs en mode débogage est probablement tout aussi importante que la limitation des rapports d'erreurs de production, on peut donc noter qu'une solution est nécessaire pour gérer cette valeur limitant le seuil de journalisation.
frattaro
2
@NickBull J'ai procédé à la rétro-ingénierie de plusieurs modules JavaScript de Facebook en 2011-2012; c'est là que je l'ai trouvé.
Jens Roland
1
@NickBull vient de vérifier mes anciens fichiers, il y en avait encore. J'ai trouvé cette astuce dans le module de chargeur de démarrage de Facebook: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(il est vrai que le code ne limite pas toutes les erreurs, seulement une classe spécifique d'erreurs de temporisation)
Jens Roland
7

IHMO, vous devez utiliser la gestion des erreurs en javascript comme vous le faites dans plusieurs autres langages (AFAIK: Python, Java).

Pour une meilleure lisibilité (et probablement de meilleures performances, même si je ne suis pas sûr que cela ait un impact vraiment important), vous devez utiliser le bloc try / catch principalement dans les cas suivants:

  • La partie du code que vous souhaitez encapsuler est une partie clé de tout l'algorithme . En cas d'échec, il pourrait:

    • créer des erreurs sur la partie suivante des codes (par exemple parce qu'il manque une var ...)
    • faire en sorte que la page ne ressemble pas à ce que l'on attend (impact sur le contenu ou css)
    • rendre les résultats étranges à l'utilisateur (impact sur le comportement du code)
  • Vous savez que le code que vous écrivez n'est pas compatible avec tous les navigateurs

  • Vous avez prévu que le code échoue (car il n'y a pas d'autre moyen de vérifier qu'il devrait fonctionner si ... alors ... bloque)
  • Et aussi lorsque vous souhaitez déboguer sans déranger l'utilisateur final

Finalement, les experts javascript peuvent avoir d'autres éléments à donner.

mes 2 cents à la boîte,

Cordialement,

Max

JMax
la source
1
"La partie du code que vous souhaitez encapsuler est une partie clé de tout l'algorithme" - peut dépendre de la manière dont vous souhaitez gérer l'échec. Si vous savez qu'il n'y a aucun moyen de continuer avec l'algorithme en cas d'échec, il peut être préférable d'envelopper le tout dans un try / catch car si votre try / catch est (par exemple) enterré dans des boucles imbriquées, ce sera plus un coup de performance . D'un autre côté, si vous pouvez prendre des mesures en cas d'exception et continuer avec l'algorithme, vous aurez besoin d'une configuration try / catch plus fine.
nnnnnn
5

En plus des autres réponses: une chose importante est d' utiliser les données de contexte disponibles dans les objets d'erreur JavaScript et dans les window.onerrorparamètres de fonction.

Des choses comme le stacktrace (errorObject.stack), le nom de fichier, le numéro de ligne et le numéro de colonne. Notez que chaque navigateur a quelques différences ... alors faites de votre mieux pour obtenir de belles erreurs.

Il peut même y avoir des problèmes avec l' objet console lui-même . J'utilise une fonction window.onerror personnalisée inspirée de celle-ci et une fonction spéciale pour tracer tout objet d'erreur standard donné inspiré de ce code .

Un autre bon point est d'inclure la version de votre application Web quelque part près du stacktrace (pour une copie et un collage rapides et sûrs). Vous pouvez également afficher les erreurs de manière plus agressive (alerte ...) en mode développement car les développeurs ne surveilleront pas en permanence la console du navigateur et risquent de ne pas voir certains des problèmes.

Utilisez également éviter d'utiliser throw 'My message', utilisez throw new Error('My message'), vous pouvez même avoir des erreurs personnalisées, lisez cet article .

Ajoutez toujours du contexte aux erreurs (la version, l'id de l'objet, un message personnalisé, ...) et assurez-vous également de faire une distinction entre les erreurs externes (certaines données externes ou circonstance ont fait échouer votre système) et les erreurs internes / assertions (votre propre système est en panne), lisez à propos de « Conception par contrat ».

Voici un guide .

Pensez également à utiliser la gestion générale des erreurs comme les intercepteurs de vos bibliothèques et frameworks:

Christophe Roussy
la source