Node.js
Undantagshantering
Sök…
Hantera undantag i Node.Js
Node.js har tre grundläggande sätt att hantera undantag / fel:
- prova - fånga blocket
- fel som det första argumentet till ett
callback
-
emit
en felhändelse användning eventEmitter
try-catch används för att fånga de undantag som kastas från körningen av synkron kod. Om den som ringer (eller den som ringer upp, ...) använde try / catch, kan de fånga felet. Om ingen av de anropande hade försökt fånga än programmet kraschar.
Om man använder try-catch på en async-operation och undantag kastades från återuppringning av async-metoden än kommer det inte att fångas av try-catch. För att få ett undantag från återuppringning av asynkoperationer föredras det att använda löften .
Exempel för att förstå det bättre
// ** 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
återuppringningar används mest i Node.js eftersom återuppringning levererar en händelse asynkront. Användaren ger dig en funktion (återuppringningen) och du åberopar den någon gång senare när den asynkrona operationen är klar.
Det vanliga mönstret är att återuppringningen anropas som en återuppringning (fel, resultat) , där endast ett av fel och resultat är icke-noll, beroende på om operationen lyckades eller misslyckades.
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 För mer komplicerade fall, istället för att använda ett återuppringning, kan själva funktionen returnera ett EventEmitter-objekt, och den som ringer förväntas lyssna på felhändelser på sändaren.
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
});
Obehandlad undantagshantering
Eftersom Node.js körs på en enda process är undantagna undantag ett problem att vara medvetna om när man utvecklar applikationer.
Tyst hantering av undantag
De flesta människor låter node.js-server (-er) tyst svälja upp felen.
- Tyst hantering av undantaget
process.on('uncaughtException', function (err) {
console.log(err);
});
Det här är dåligt , det kommer att fungera men:
Rotorsaken kommer att förbli okänd, eftersom den inte kommer att bidra till att lösa vad som orsakade undantaget (fel).
Vid databasanslutning (pool) blir av någon anledning stängd kommer detta att resultera i konstant spridning av fel, vilket innebär att servern kommer att köras men den kommer inte att ansluta till db igen.
Återgår till initialtillstånd
I händelse av en "uncovedException" är det bra att starta om servern och återställa den till sitt ursprungliga tillstånd , där vi vet att den kommer att fungera. Undantag är loggat, applikationen avslutas men eftersom det kommer att köras i en behållare som kommer att se till att servern körs uppnår vi omstart av servern (återgår till det ursprungliga arbetsläget).
- Installera forever (eller annat CLI-verktyg för att se till att nodservern körs kontinuerligt)
npm install forever -g
- Starta servern för alltid
forever start app.js
Anledning till varför det startas och varför vi använder för evigt är när servern är avslutad för alltid kommer processen att starta servern igen.
- Starta om servern
process.on('uncaughtException', function (err) {
console.log(err);
// some logging mechanisam
// ....
process.exit(1); // terminates process
});
På en sidnot var det också ett sätt att hantera undantag med kluster och domäner .
Domäner avskrivs mer information här .
Fel och löften
Löften hanterar fel annorlunda än synkron eller återuppringningsdriven kod.
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!
});
för närvarande resulterar fel som kastas i ett löfte som inte fångas i att felet sväljs, vilket kan göra det svårt att spåra felet. Detta kan lösas med hjälp av luddning verktyg som eslint eller genom att se till att du alltid har en catch
klausul.
Detta beteende avskrivs i nod 8 för att avsluta nodprocessen.