Node.js
Gestion des exceptions
Recherche…
Gestion des exceptions dans Node.Js
Node.js dispose de 3 méthodes de base pour gérer les exceptions / erreurs:
- essayer - attraper le bloc
- erreur comme premier argument d'un
callback
-
emit
un événement d' erreur en utilisant eventEmitter
try-catch est utilisé pour intercepter les exceptions lancées à partir de l'exécution du code synchrone. Si l'appelant (ou l'appelant de l'appelant, ...) a essayé / rattrapé, il peut alors détecter l'erreur. Si aucun des appelants n’a essayé, le programme se bloque.
Si vous utilisez try-catch sur une opération asynchrone et que l'exception est renvoyée par le rappel de la méthode asynchrone, elle ne sera pas interceptée par try-catch. Pour intercepter une exception de rappel d'opération asynchrone, il est préférable d'utiliser des promesses .
Exemple pour mieux comprendre
// ** Example - 1 **
function doSomeSynchronousOperation(req, res) {
if(req.body.username === ''){
throw new Error('User Name cannot be empty');
}
return true;
}
// calling the method above
try {
// synchronous code
doSomeSynchronousOperation(req, res)
catch(e) {
//exception handled here
console.log(e.message);
}
// ** Example - 2 **
function doSomeAsynchronousOperation(req, res, cb) {
// imitating async operation
return setTimeout(function(){
cb(null, []);
},1000);
}
try {
// asynchronous code
doSomeAsynchronousOperation(req, res, function(err, rs){
throw new Error("async operation exception");
})
} catch(e) {
// Exception will not get handled here
console.log(e.message);
}
// The exception is unhandled and hence will cause application to break
Les callbacks sont principalement utilisés dans Node.js car le callback délivre un événement de manière asynchrone. L'utilisateur vous transmet une fonction (le rappel) et vous l'appelez plus tard lorsque l'opération asynchrone est terminée.
Le schéma habituel est que le rappel est appelé comme un rappel (err, result) , où un seul des erreurs et des résultats est non nul, selon que l'opération a réussi ou échoué.
function doSomeAsynchronousOperation(req, res, callback) {
setTimeout(function(){
return callback(new Error('User Name cannot be empty'));
}, 1000);
return true;
}
doSomeAsynchronousOperation(req, res, function(err, result) {
if (err) {
//exception handled here
console.log(err.message);
}
//do some stuff with valid data
});
emit Pour des cas plus compliqués, au lieu d'utiliser un rappel, la fonction elle-même peut renvoyer un objet EventEmitter, et l'appelant est censé écouter les événements d'erreur sur l'émetteur.
const EventEmitter = require('events');
function doSomeAsynchronousOperation(req, res) {
let myEvent = new EventEmitter();
// runs asynchronously
setTimeout(function(){
myEvent.emit('error', new Error('User Name cannot be empty'));
}, 1000);
return myEvent;
}
// Invoke the function
let event = doSomeAsynchronousOperation(req, res);
event.on('error', function(err) {
console.log(err);
});
event.on('done', function(result) {
console.log(result); // true
});
Gestion des exceptions non maîtrisées
Étant donné que Node.js s'exécute sur un seul processus, les exceptions non interceptées constituent un problème à prendre en compte lors du développement d'applications.
Gestion silencieuse des exceptions
La plupart des personnes ont laissé le ou les serveurs node.js avaler les erreurs en silence.
- Manipulation silencieuse de l'exception
process.on('uncaughtException', function (err) {
console.log(err);
});
C'est mauvais , ça marchera mais:
La cause première restera inconnue, car elle ne contribuera pas à la résolution de ce qui a causé l’exception (erreur).
En cas de connexion à une base de données (pool) fermée pour une raison quelconque, cela entraînera une propagation constante des erreurs, ce qui signifie que le serveur fonctionnera mais ne se reconnectera pas à la base de données.
Retourner à l'état initial
En cas d’exception "uncaughtException", il est bon de redémarrer le serveur et de le ramener à son état initial , où nous savons qu’il fonctionnera. L'exception est consignée, l'application est terminée, mais étant donné qu'elle s'exécutera dans un conteneur qui s'assurera que le serveur fonctionne, nous allons redémarrer le serveur (en revenant à son état de fonctionnement initial).
- Installer le pour toujours (ou un autre outil CLI pour s'assurer que le serveur de noeuds fonctionne en continu)
npm install forever -g
- Démarrer le serveur pour toujours
forever start app.js
Raison pour laquelle est-il commencé et pourquoi nous utilisons pour toujours est après que le serveur est arrêté pour toujours, le processus va redémarrer le serveur.
- Redémarrer le serveur
process.on('uncaughtException', function (err) {
console.log(err);
// some logging mechanisam
// ....
process.exit(1); // terminates process
});
Sur un côté, il y avait un moyen de gérer les exceptions avec les clusters et les domaines .
Les domaines sont obsolètes plus d'informations ici .
Erreurs et promesses
Les promesses traitent les erreurs différemment du code synchrone ou du code de rappel.
const p = new Promise(function (resolve, reject) {
reject(new Error('Oops'));
});
// anything that is `reject`ed inside a promise will be available through catch
// while a promise is rejected, `.then` will not be called
p
.then(() => {
console.log("won't be called");
})
.catch(e => {
console.log(e.message); // output: Oops
})
// once the error is caught, execution flow resumes
.then(() => {
console.log('hello!'); // output: hello!
});
Actuellement, les erreurs dans une promesse qui ne sont pas détectées entraînent une erreur, ce qui peut rendre difficile le suivi de l'erreur. Cela peut être résolu en utilisant des outils de peluches comme eslint ou en vous assurant de toujours avoir une clause de catch
.
Ce comportement est obsolète dans le noeud 8 en faveur de la fin du processus de noeud.