我的用例正在发送自定义JSON错误消息,因为我正在使用express来驱动我的REST API。我认为这是一个相当普遍的情况,因此在我的回答中将重点介绍该情况。
精简版:
快速错误处理
定义错误处理中间件,就像其他中间件一样,除了使用四个参数而不是三个参数外,特别是使用签名(err,req,res,next)。...在其他app.use()之后,您最后定义错误处理中间件并路由调用
app.use(function(err, req, res, next) {
if (err instanceof JSONError) {
res.status(err.status).json({
status: err.status,
message: err.message
});
} else {
next(err);
}
});
通过执行以下操作从代码的任何位置引发错误:
var JSONError = require('./JSONError');
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);
长版
引发错误的规范方法是:
var err = new Error("Uh oh! Can't find something");
err.status = 404;
next(err)
默认情况下,Express通过将其整洁地打包为带有代码404的HTTP响应和包含消息字符串并附加了堆栈跟踪的主体来处理此问题。
例如,当我使用Express作为REST服务器时,这对我不起作用。我希望将错误以JSON而不是HTML的形式发送回去。我也绝对不希望将堆栈跟踪移到我的客户端。
我可以使用发送JSON作为响应req.json()
,例如。像req.json({ status: 404, message: 'Uh oh! Can't find something'})
。(可选)我可以使用设置状态代码req.status()
。结合两者:
req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
这就像一个魅力。就是说,我发现每次遇到错误时都很难键入代码,并且代码不再像next(err)
以前那样自我记录。它看起来与发送正常(即有效)响应JSON的方式非常相似。此外,规范方法引发的任何错误仍将导致HTML输出。
这是Express的错误处理中间件出现的地方。作为我的路线的一部分,我定义了:
app.use(function(err, req, res, next) {
console.log('Someone tried to throw an error response');
});
我还将Error细分为自定义JSONError类:
JSONError = function (status, message) {
Error.prototype.constructor.call(this, status + ': ' + message);
this.status = status;
this.message = message;
};
JSONError.prototype = Object.create(Error);
JSONError.prototype.constructor = JSONError;
现在,当我想在代码中引发错误时,我做了:
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);
回到自定义错误处理中间件,我将其修改为:
app.use(function(err, req, res, next) {
if (err instanceof JSONError) {
res.status(err.status).json({
status: err.status,
message: err.message
});
} else {
next(err);
}
}
将Error子类化为JSONError很重要,因为我怀疑Express会instanceof Error
检查传递给的第一个参数,next()
以确定是否必须调用普通处理程序或错误处理程序。我可以删除该instanceof JSONError
检查并进行较小的修改以确保意外错误(例如崩溃)也返回JSON响应。