文字

以与其他中间件功能相同的方式定义错误处理中间件函数,但错误处理函数有四个参数而不是三个:(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()代码中的错误,即使自定义错误处理中间件已就位,也可以触发默认错误处理程序。

上一篇:下一篇: