错误处理中间件函数的定义方式与其他中间件函数基本相同,差别在于错误处理函数有四个自变量而不是三个:(err, req, res, next)
:例如:
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
请在其他 app.use()
和路由调用之后,最后定义错误处理中间件,例如:
const bodyParser = require('body-parser')
const methodOverride = require('method-override')
app.use(bodyParser())
app.use(methodOverride())
app.use((err, req, res, next) => {
// logic
})
中间件函数中的响应可以采用您首选的任何格式,例如,HTML 错误页、简单消息或 JSON 字符串。
出于组织(和更高级框架)的目的,可以定义若干错误处理中间件函数,这和对常规中间件函数的处理很相似。例如,如果您希望为使用 XHR
发出的请求以及未使用此对象发出的请求定义错误处理程序,可以使用以下命令:
const bodyParser = require('body-parser')
const 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',
(req, res, next) => {
if (!req.user.hasPaid) {
// continue handling this request
next('route')
}
}, (req, res, next) => {
PaidContent.find((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 })
}