Maison >interface Web >js tutoriel >Comment gérer les exceptions JavaScript
Les programmeurs rencontreront certainement des erreurs lors de l'écriture de programmes. Cet article est basé sur le concept de gestion des erreurs en JavaScript. J'espère que cela vous aidera lorsque vous écrirez des programmes JavaScript.
Démo
La démo que nous utilisons peut être téléchargée depuis GitHub Lorsque le programme est exécuté, la page suivante apparaîtra :
.
Tous les boutons déclencheront des erreurs et lanceront TypeError. Voici la définition de ce module :
// scripts/error.jsfunction error() {var foo = {};return foo.bar();}
Un objet vide foo est défini dans error(), donc appeler foo.bar() provoquera est défini et une erreur est signalée. Nous utilisons des tests unitaires pour vérifier :
// tests/scripts/errorTest.jsit('throws a TypeError', function () {should.throws(error, TypeError);});
Nous utilisons Mocha avec Should.js pour les tests unitaires.
Après avoir cloné la base de code et installé les packages de dépendances, vous pouvez utiliser npm t pour exécuter des tests. Bien sûr, vous pouvez également exécuter un fichier de test, tel que : ./node_modules/mocha/bin/mocha tests/scripts/errorTest.js
Croyez-moi, pour un langage dynamique comme JavaScript, peu importe qui c'est facile de rencontrer des erreurs comme celle-ci.
Méthode de manipulation incorrecte
J'ai résumé la fonction de traitement des événements correspondant au bouton un peu plus simple, comme suit :
// scripts/badHandler.jsfunction badHandler(fn) {try {return fn();} catch (e) { }return null;}
badHandler reçoit un fn As une fonction de rappel, la fonction de rappel est appelée dans badHandler. Nous écrivons le test unitaire correspondant :
// tests/scripts/badHandlerTest.jsit('returns a value without errors', function() {var fn = function() {return 1;};var result = badHandler(fn);result.should.equal(1);});it('returns a null with errors', function() {var fn = function() {throw new Error('random error');};var result = badHandler(fn);should(result).equal(null);});
Vous constaterez que si une exception se produit, badHandler renvoie simplement null. Si vous faites correspondre le code complet, vous trouverez le problème :
// scripts/badHandlerDom.js(function (handler, bomb) {var badButton = document.getElementById('bad'); if (badButton) {badButton.addEventListener('click', function () {handler(bomb);console.log('Imagine, getting promoted for hiding mistakes');}); }}(badHandler, error));
Si vous essayez de l'attraper lorsqu'une erreur se produit, puis que vous renvoyez simplement null, je ne trouve pas ce qui n'a pas fonctionné du tout. Cette stratégie silencieuse peut entraîner une confusion dans l'interface utilisateur et dans les données, et vous pouvez passer plusieurs heures à déboguer mais ignorer le code dans try-catch, qui est la source du désastre. Si le code est si complexe qu’il comporte plusieurs niveaux d’appels, il sera presque impossible de trouver ce qui n’a pas fonctionné. Par conséquent, nous ne recommandons pas d’utiliser la stratégie de défaillance silencieuse, nous avons besoin d’une approche plus élégante.
Pas mal mais mauvaise manière
// scripts/uglyHandler.jsfunction uglyHandler(fn) {try {return fn();} catch (e) {throw new Error('a new error');}}
La façon dont il gère les erreurs est d'attraper l'erreur e, puis de générer une nouvelle erreur. C’est en effet mieux que la stratégie précédente d’échec silencieux. Si quelque chose ne va pas, je peux revenir en arrière couche par couche jusqu'à ce que je trouve l'erreur e qui a été initialement générée. Le simple fait de lancer une erreur (« une nouvelle erreur ») contient des informations limitées et n'est pas précis. Nous personnalisons l'objet d'erreur et envoyons plus d'informations :
// scripts/specifiedError.js// Create a custom errorvar SpecifiedError = function SpecifiedError(message) {this.name = 'SpecifiedError';this.message = message || '';this.stack = (new Error()).stack;}; SpecifiedError.prototype = new Error();SpecifiedError.prototype.constructor = SpecifiedError; 、// scripts/uglyHandlerImproved.jsfunction uglyHandlerImproved(fn) {try {return fn();} catch (e) {throw new SpecifiedError(e.message);}}// tests/scripts/uglyHandlerImprovedTest.jsit('returns a specified error with errors', function () {var fn = function () {throw new TypeError('type error');};should.throws(function () {uglyHandlerImproved(fn);}, SpecifiedError);});
Cette personnalisation. L'objet d'erreur contient désormais les informations d'erreur d'origine et devient donc plus utile. Mais comme il a été lancé à nouveau, il s’agissait toujours d’une erreur non gérée.
Intercepter les exceptions
Une idée est d'entourer toutes les fonctions avec try...catch :
function main(bomb) {try {bomb();} catch (e) {// Handle all the error things}}
Cependant, un tel code deviendra très volumineux, illisible et inefficace. Vous en souvenez-vous encore ? Au début de cet article, nous avons mentionné qu'une exception en JavaScript n'est qu'un événement. Heureusement, il existe une méthode globale de gestion des événements d'exception (onerror).
// scripts/errorHandlerDom.jswindow.addEventListener('error', function (e) {var error = e.error;console.log(error);});
Obtenir des informations sur la pile
Vous pouvez envoyer des informations d'erreur au serveur :
// scripts/errorAjaxHandlerDom.jswindow.addEventListener('error', function (e) {var stack = e.error.stack;var message = e.error.toString();if (stack) {message += '\n' + stack;} var xhr = new XMLHttpRequest();xhr.open('POST', '/log', true);// Fire an Ajax request with error detailsxhr.send(message);});
Afin d'obtenir des informations d'erreur plus détaillées et d'enregistrer dans Pour éviter les problèmes de traitement des données, vous pouvez également utiliser le plug-in de surveillance JavaScript de fundebug pour accéder rapidement au service de surveillance des bogues en trois minutes.
Voici le message d'erreur reçu par le serveur :
Si votre script est placé sous un autre nom de domaine, si vous n'activez pas CORS, sauf pour Erreur de script., vous ne verrez aucune information d’erreur utile. Si vous souhaitez connaître la solution spécifique, veuillez vous référer à : Erreur de script.
Gestion des erreurs asynchrones
Étant donné que setTimeout est exécuté de manière asynchrone, l'exception de code suivante ne sera pas interceptée par try...catch :
// scripts/asyncHandler.jsfunction asyncHandler(fn) {try {// This rips the potential bomb from the current contextsetTimeout(function () {fn();}, 1);} catch (e) { }}
L'instruction try...catch ne capturera que les exceptions dans l'environnement d'exécution actuel. Mais lorsque l'exception ci-dessus est levée, l'interpréteur JavaScript n'est plus en try...catch, il ne peut donc pas être intercepté. Il en va de même pour toutes les requêtes Ajax.
Nous pouvons apporter une légère amélioration et écrire try...attraper le rappel de la fonction asynchrone :
setTimeout(function () {try {fn();} catch (e) {// Handle this async error}}, 1);
Cependant, une telle routine En conséquence, le projet est plein de try...catch et le code est très concis. De plus, le moteur V8 qui exécute JavaScript décourage l'utilisation des fonctions try...catch in. Heureusement, nous n'avons pas besoin de faire cela, la gestion globale des erreurs détectera ces erreurs.
Conclusion
Mon conseil est de ne pas cacher vos erreurs, d’être assez courageux pour les rejeter. Personne ne devrait avoir honte car un bug dans le code provoque le crash du programme. Nous pouvons interrompre le programme et laisser l'utilisateur recommencer. Les erreurs sont inévitables, ce qui compte, c'est la façon dont vous les gérez.
Le contenu ci-dessus explique comment gérer les erreurs JavaScript. Si vous le trouvez utile, veuillez l'enregistrer rapidement.
Recommandations associées :
Erreur de base de données MySQL : solution de trop de connexions
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!