Node.js
Obsługa wyjątków
Szukaj…
Obsługa wyjątku w Node.Js
Node.js ma 3 podstawowe sposoby obsługi wyjątków / błędów:
- spróbuj złapać blok
- błąd jako pierwszy argument
callback
-
emit
zdarzenie błędu za pomocą eventEmitter
try-catch służy do wychwytywania wyjątków zgłaszanych podczas synchronicznego wykonywania kodu. Jeśli osoba dzwoniąca (lub osoba dzwoniąca, ...) zastosowała try / catch, może złapać błąd. Jeśli żaden z rozmówców nie próbował złapać, program ulega awarii.
Jeśli użycie try-catch w operacji asynchronicznej spowoduje zgłoszenie wyjątku z wywołania zwrotnego metody asynchronicznej, wówczas nie zostanie on złapany przez try-catch. Aby wychwycić wyjątek od wywołania zwrotnego operacji asynchronicznej, zaleca się stosowanie obietnic .
Przykład, aby lepiej to zrozumieć
// ** 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
wywołania zwrotne są najczęściej używane w Node.js, ponieważ wywołanie zwrotne dostarcza zdarzenie asynchronicznie. Użytkownik przekazuje ci funkcję (wywołanie zwrotne) i wywołujesz ją później, gdy zakończy się operacja asynchroniczna.
Zwykle wzorzec polega na tym, że wywołanie zwrotne jest wywoływane jako wywołanie zwrotne (err, wynik) , przy czym tylko jedno z err i wynik ma wartość inną niż null, w zależności od tego, czy operacja się powiodła, czy nie.
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 W przypadku bardziej skomplikowanych przypadków, zamiast korzystania z wywołania zwrotnego, sama funkcja może zwrócić obiekt EventEmitter i oczekuje się, że osoba dzwoniąca będzie nasłuchiwała zdarzeń błędów na emiterze.
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
});
Zarządzanie nieobsługiwanymi wyjątkami
Ponieważ Node.js działa na jednym procesie, nieprzechwycone wyjątki stanowią problem, o którym należy pamiętać przy programowaniu aplikacji.
Cicha obsługa wyjątków
Większość osób pozwala serwerom node.js cicho połykać błędy.
- Cicha obsługa wyjątku
process.on('uncaughtException', function (err) {
console.log(err);
});
To źle , będzie działać, ale:
Przyczyna pierwotna pozostanie nieznana, ponieważ nie przyczyni się do rozwiązania przyczyny wyjątku (błędu).
W przypadku, gdy połączenie z bazą danych (pula) zostanie z jakiegoś powodu zamknięte, spowoduje to ciągłe propagowanie błędów, co oznacza, że serwer będzie działał, ale nie połączy się ponownie z db.
Powrót do stanu początkowego
W przypadku „nieprzechwyconego wyjątku” dobrze jest zrestartować serwer i przywrócić go do stanu początkowego , o którym wiemy, że będzie działał. Wyjątek jest rejestrowany, aplikacja zostaje zakończona, ale ponieważ będzie działała w kontenerze, który zapewni, że serwer działa, osiągniemy restart serwera (powrót do początkowego stanu roboczego).
- Instalowanie na zawsze (lub inne narzędzie CLI, aby upewnić się, że serwer węzła działa nieprzerwanie)
npm install forever -g
- Uruchamianie serwera na zawsze
forever start app.js
Powód, dla którego został uruchomiony i dlaczego używamy go na zawsze, następuje po tym, jak serwer zostanie zakończony na zawsze, proces uruchomi serwer ponownie.
- Ponowne uruchomienie serwera
process.on('uncaughtException', function (err) {
console.log(err);
// some logging mechanisam
// ....
process.exit(1); // terminates process
});
Na marginesie istniał również sposób radzenia sobie z wyjątkami z klastrami i domenami .
Domeny są przestarzałe, więcej informacji tutaj .
Błędy i obietnice
Obiecuje obsługiwać błędy inaczej niż kod synchroniczny lub kod wywołania zwrotnego.
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!
});
obecnie błędy zgłoszone w obietnicy, która nie została złapana, powodują połknięcie błędu, co może utrudnić jego wyśledzenie. Można to rozwiązać za pomocą narzędzi do szorowania, takich jak eslint lub upewniając się, że zawsze masz klauzulę catch
.
To zachowanie jest przestarzałe w węźle 8 na korzyść zakończenia procesu węzła.