Как правильно обрабатывать ошибки в Express?
Я начинаю работать с Express JS и сталкиваюсь с проблемой. Я не могу понять, как правильно обрабатывать ошибки.
Например, у меня есть API веб-сервисов, который обслуживает объект, называемый "событие". Я хотел бы вернуть простую строку "не могу найти событие", когда пользователь отправляет идентификатор события, который не найден. Вот как я сейчас структурирую свой код:
app.get('/event/:id', function(req, res, next) {
if (req.params.id != 1) {
next(new Error('cannot find event ' + req.params.id));
}
req.send('event found!');
});
Когда я отправляю идентификатор, отличный от 1, Node выходит со следующим выходом:
http.js:527
throw new Error("Can't set headers after they are sent.");
^
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/usr/local/kayak/node_modules/express/node_modules/connect/lib/patch.js:62:20)
at /usr/local/kayak/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js:72:19
at [object Object].<anonymous> (fs.js:107:5)
at [object Object].emit (events.js:61:17)
at afterRead (fs.js:878:12)
at wrapper (fs.js:245:17)
Из того, что я могу сказать, используя отладчик node.js, выполнение блока кода продолжается после вызова next()
, что означает, что req.send('event found!')
пытается запустить. Я не хочу, чтобы это произошло.
Единственным обходным решением, которое я нашел, является просто выбросить new Error()
вместо "next-ing", но это приводит к созданию страницы ошибки HTML Express по умолчанию. Я бы хотел получить немного больше контроля.
Я потратил время, чтобы прочитать раздел обработки ошибок документации Express, но я не мог этого понять.
Ответы
Ответ 1
Вы хотите проверить Экспресс-обработку ошибок. Оттуда:
app.param('userId', function(req, res, next, id) {
User.get(id, function(err, user) {
if (err) return next(err);
if (!user) return next(new Error('failed to find user'));
req.user = user;
next();
});
});
В sweetspot, который вам не хватает, находится return
next(...)
Ответ 2
Это потому, что вы делаете это неправильно: вы уже выбросили ошибку (которая будет обработана Express и вернет страницу с ошибкой 500) для пользователя или что-то в этом роде), но вы также пытаетесь отправить свой собственный ответ на клиент: res.send( "событие найдено!" );
Вы действительно должны проверить руководство Express об обработке ошибок здесь: http://expressjs.com/guide/error-handling.html
Что я буду делать в вашем примере:
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
app.get('/event/:id', function(req, res, next){
if (req.params.id != 1) {
throw new NotFound('Cannot find event ' + req.params.id);
} else {
res.send('event found!');
}
});
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.ejs');
} else {
next(err);
}
});
Ответ 3
В вашем коде есть несколько проблем:
-
При ответе на клиента вам нужно использовать объект response (res
, а не req
).
-
При отправке ошибки в next
вы должны вернуть, так что остальная часть функции не будет выполняться.
Вот ваш код после исправления этих ошибок:
app.get('/event/:id', function(req, res, next) {
if (req.params.id != 1) {
return next(new Error('cannot find event ' + req.params.id));
}
res.send('event found!'); // use res.send (NOT req.send)
});