错误处理中间件函数的定义方式与其他中间件函数基本相同,差别在于错误处理函数有四个自变量而不是三个:(err, req, res, next)
:例如:
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
请在其他 app.use()
和路由调用之后,最后定义错误处理中间件,例如:
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(bodyParser());
app.use(methodOverride());
app.use(function(err, req, res, next) {
// logic
});
中间件函数中的响应可以采用您首选的任何格式,例如,HTML 错误页、简单消息或 JSON 字符串。
出于组织(和更高级框架)的目的,可以定义若干错误处理中间件函数,这和对常规中间件函数的处理很相似。例如,如果您希望为使用 XHR
发出的请求以及未使用此对象发出的请求定义错误处理程序,可以使用以下命令:
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(bodyParser());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
在此示例中,通用 logErrors
可能将请求和错误信息写入 stderr
,例如:
function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
也是在此示例中,clientErrorHandler
定义如下,错误会显式传递到下一项:
function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' });
} else {
next(err);
}
}
“catch-all”errorHandler
函数可以如下实现:
function errorHandler(err, req, res, next) {
res.status(500);
res.render('error', { error: err });
}
如果将任何项传递到 next()
函数(除了字符串 'route'
),那么 Express 会将当前请求视为处于错误状态,并跳过所有剩余的非错误处理路由和中间件函数。如果您希望以某种方式处理此错误,必须如下一节中所述创建一个错误处理路由。
如果一个路由处理程序具有多个回调函数,那么可以使用 route
参数跳至下一个路由处理程序。例如:
app.get('/a_route_behind_paywall',
function checkIfPaidSubscriber(req, res, next) {
if(!req.user.hasPaid) {
// continue handling this request
next('route');
}
}, function getPaidContent(req, res, next) {
PaidContent.find(function(err, doc) {
if(err) return next(err);
res.json(doc);
});
});
在此示例中,将跳过 getPaidContent
处理程序,而将继续执行 /a_route_behind_paywall
的 app
中所有剩余的处理程序。
对 next()
和 next(err)
的调用会表明当前处理程序是否完整以及处于何种状态。next(err)
将跳过链中所有剩余的处理程序(设置为按上述方式处理错误的处理程序除外)。
Express 随附一个内置的错误处理程序,负责处理应用程序中可能遇到的任何错误。这个缺省的错误处理中间件函数添加在中间件函数集的末尾。
如果将错误传递到 next()
且未在错误处理程序中进行处理,那么该错误将由内置的错误处理程序处理;错误将写入客户机的堆栈跟踪内。堆栈跟踪不包含在生产环境中。
将环境变量 NODE_ENV
设置为 production
,以生产方式运行此应用程序。
如果在开始写响应之后调用 next()
时出错(例如,如果在以流式方式将响应传输到客户机时遇到错误),Express 缺省错误处理程序会关闭连接并使请求失败。
因此,在添加定制错误处理程序时,如果头已发送到客户机,您可能希望委托给 Express 中的缺省错误处理机制处理:
function errorHandler(err, req, res, next) {
if (res.headersSent) {
return next(err);
}
res.status(500);
res.render('error', { error: err });
}