5.错误处理 | 5. Error handling
错误处理
以与其他中间件功能相同的方式定义错误处理中间件函数,但错误处理函数有四个参数而不是三个:(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.urlencoded{
extended: true
}))
app.use(bodyParser.json())
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.urlencoded{
extended: true
}))
app.use(bodyParser.json())
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
定义如下:在这种情况下,错误会显式传递给下一个错误。
请注意,如果不在
错误处理函数中调用“next”,则需要负责编写(并结束)响应。否则,这些请求将“挂起”并且不符合垃圾回收的条件。
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')
}
else{
next(
}
}, function getPaidContent (req, res, next) {
PaidContent.find(function (err, doc) {
if (err) return next(err)
res.json(doc)
})
})
在这个例子中,getPaidContent
处理程序将被跳过,但在任何剩余处理app时将
继续要执行/a_route_behind_paywall
。
调用next()
和next(err)
指出当前处理程序已完成并处于何种状态。next(err)
将会跳过链中所有剩余的处理程序,除了那些设置为处理错误的处理程序,如上所述。
默认错误处理程序
Express带有一个内置的错误处理程序,它处理应用程序中可能遇到的任何错误。这个默认的错误处理中间件功能被添加到中间件功能堆栈的末尾。
如果你传递一个错误next()
并且你没有在错误处理器中处理它,它将由内置的错误处理器来处理; 该错误将通过堆栈跟踪写入客户端。生产环境中不包含堆栈跟踪。
为production
设置环境变量ODE_ENV
,运行在生产模式下的应用程序。
如果您调用next()
响应后发生错误(例如,如果在将响应传输到客户端时遇到错误),Express默认错误处理程序将关闭连接并使请求失败。
因此,当您添加自定义错误处理程序时,您将希望在头文件已经发送到客户端时委派到Express中的默认错误处理机制:
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
请注意,如果您多次调用next()
代码中的错误,即使自定义错误处理中间件已就位,也可以触发默认错误处理程序。