Восстановление из невольного исключения в Node.JS
Хорошо, поэтому у меня проблема. Если возникает неперехваченное исключение, когда я обрабатываю HTTP-запрос, у меня нет возможности вызвать метод end() для объекта http.ServerResponse. Поэтому сервер зависает вечно и никогда не выполняет запрос.
Вот пример:
var express = require('express');
var app = express.createServer();
var reqNum = 0;
app.get('/favicon.ico', function(req, res) {res.send(404);});
app.get('*', function(req, res, next) {
console.log("Request #", ++reqNum, ":", req.url);
next();
});
app.get('/error', function(req, res, next) {
throw new Error("Problem occurred");
});
app.get('/hang', function(req, res, next) {
console.log("In /hang route");
setTimeout(function() {
console.log("In /hang callback");
if(reqNum >= 3)
throw new Error("Problem occurred");
res.send("It worked!");
}, 2000);
});
process.on('uncaughtException', function(err) {
console.log("Uncaught exception!", err);
});
app.listen(8080);
При посещении/ошибке возникает исключение, но оно ловутся. Пользователь получает сообщение об ошибке - никаких проблем. Если я посещу/повесить, сервер, в конце концов, выкинет исключенное исключение и зависнет вечно. Любые последующие запросы/зависание будут висеть.
Это отстой. Любые советы по устранению этой проблемы?
Ответы
Ответ 1
Когда происходит неперехваченное исключение, вы находитесь в нечистом состоянии. Пусть процесс умирает и перезапускает его, и вы ничего не можете сделать, чтобы безопасно вернуть его в хорошо известное состояние. Используйте forever
, он перезапустит ваш процесс, как только он умрет.
Ответ 2
Если ошибка генерируется синхронно, экспресс не перестает работать, возвращая только 500.
this.app.get("/error", (request, response) => {
throw new Error("shouldn't stop");
});
Если ошибка генерируется асинхронно, экспресс завершится сбоем. Но согласно официальной документации, все еще есть способ восстановиться, вызвав next
:
this.app.get("/error", (request, response, next) => {
setTimeout(() => {
try {
throw new Error("shouldn't stop");
} catch (err) {
next(err);
}
}, 0);
});
Это позволит express выполнить свою обязанность ответить с ошибкой 500.
Ответ 3
Используйте try/catch/finally.
app.get('/hang', function(req, res, next) {
console.log("In /hang route");
setTimeout(function() {
console.log("In /hang callback");
try {
if(reqNum >= 3)
throw new Error("Problem occurred");
} catch (err) {
console.log("There was an error", err);
} finally {
res.send("It worked!");
}
}, 2000);
});