web-dev-qa-db-fra.com

Principes de gestion des erreurs pour les applications Node.js + Express.js?

Il semble que le signalement/le traitement des erreurs se fasse différemment dans les applications Node.js + Express.js par rapport aux autres frameworks. Ai-je raison de comprendre que cela fonctionne comme suit?

A) Détectez erreurs en les recevant comme paramètres de vos fonctions de rappel. Par exemple:

doSomethingAndRunCallback(function(err) { 
    if(err) { … }
});

B) Report erreurs dans MIDDLEWARE en appelant next (err). Exemple:

handleRequest(req, res, next) {
    // An error occurs…
    next(err);
}

C) Report erreurs dans ROUTES en lançant l'erreur. Exemple:

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

D) Traitez erreurs en configurant votre propre gestionnaire d'erreurs via app.error () ou utilisez le gestionnaire d'erreurs générique Connect . Exemple:

app.error(function(err, req, res, next) {
    console.error(err);
    res.send('Fail Whale, yo.');
});

Ces quatre principes sont-ils à la base de toutes les procédures de traitement des erreurs et de génération de rapports dans les applications Node.js + Express.js?

175
Clint Harris

Le traitement des erreurs dans Node.js est généralement du format A). La plupart des callbacks renvoient un objet d'erreur comme premier argument ou null.

Express.js utilise un middleware et sa syntaxe utilise B) et E) (voir ci-dessous).

C) est une mauvaise pratique si vous me demandez.

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

Vous pouvez facilement réécrire ce qui précède

app.get('/home', function(req, res, next) {
    // An error occurs
    next(err);
});

La syntaxe du middleware est valide dans une requête get.

Comme pour d)

(19:26:37) tjholowaychuk: app.error est supprimé dans 3.x

TJ vient de confirmer que app.error est obsolète en faveur de E

E)

app.use(function(err, req, res, next) {
  // Only handle `next(err)` calls
});

Tout middleware ayant une longueur de 4 (4 arguments) est considéré comme un middleware d'erreur. Quand on appelle next(err), connecte et appelle un middleware à base d'erreur.

182
Raynos

Les gens de Joyent ont publié n document très instructif sur les meilleures pratiques à ce sujet. Un article à lire absolument pour tous les développeurs Node.js.

10
Nishant Shreshth

Pourquoi premier paramètre?

En raison de la nature asynchrone de Node.js, le modèle premier-paramètre-as-err est désormais bien établi en tant que convention pour le traitement des erreurs serland Node.js . C'est parce que asynchrone:

try {
    setTimeout(function() {
        throw 'something broke' //Some random error
    }, 5)
}
catch(e) {
   //Will never get caught
}

Donc, au lieu de cela, le premier argument du rappel est à peu près le seul moyen sensé de transmettre les erreurs de manière asynchrone, autrement que de simplement les lancer.

Cela entraînerait un unhandled exception qui, de la façon dont cela sonne, implique que rien n’a été fait pour que l’application sorte de son état confus.

Les exceptions, pourquoi existent-elles

Il convient toutefois de noter que pratiquement toutes les parties de Node.js sont des émetteurs d’événements et que le lancement d’une exception est un événement de bas niveau qui peut être géré comme tous les événements:

//This won't immediately crash if connection fails
var socket = require("net").createConnection(5000);
socket.on("error", function(err) {
    console.error("calm down...", err)
});

Ceci ne peut pas mais être poussé à l'extrême jusqu'à rattraper toutes les erreurs et faire une application qui essaiera très difficile de ne jamais tomber en panne. C’est une idée terrible dans presque tous les cas d’utilisation, car cela laissera le développeur sans aucune idée de ce qui se passe dans l’état de l’application, ce qui revient à insérer l’essentiel dans try-catch.

Domaines - regrouper les événements de manière logique

Dans le cadre de la résolution du problème des exceptions qui font basculer les applications, domaines permet au développeur de prendre, par exemple, l’application Express.js, et d’essayer de fermer les connexions de manière judicieuse en cas de défaillance catastrophique.

ES6

Il est probablement mentionné que cela changera à nouveau car ES6 permet au modèle de générateur de créer des événements asynchrones qui peuvent toujours être capturés avec des blocs try/catch.

Koa (écrit par TJ Holowaychuck, même auteur original d'Express.js) le fait remarquablement. Il utilise l'instruction ES6 yield pour créer des blocs qui, tout en apparaissant presque synchrones, sont gérés de la manière asynchrone habituelle des noeuds:

app.use(function *(next) {
    try {
        yield next;
    } 
    catch (err) {
        this.status = err.status || 500;
        this.body = err.message;
        this.app.emit('error', err, this);
    }
});

app.use(function *(next) {
    throw new Error('some error');
})

Cet exemple a été volé sans vergogne à ici .

3
David