首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

5.错误处理 | 5. Error handling

以与其他中间件功能相同的方式定义错误处理中间件函数,但错误处理函数有四个参数而不是三个:(err, req, res, next)。例如:

代码语言:javascript
复制
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

您最后定义错误处理中间件,在其他app.use()路由之后并路由呼叫; 例如:

代码语言:javascript
复制
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和不使用的请求定义错误处理程序,则可以使用以下命令:

代码语言:javascript
复制
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写请求和错误信息,例如:

代码语言:javascript
复制
function logErrors (err, req, res, next) {
  console.error(err.stack)
  next(err)
}

同样在这个例子中,clientErrorHandler定义如下:在这种情况下,错误会显式传递给下一个错误。

请注意,如果不在错误处理函数中调用“next”,则需要负责编写(并结束)响应。否则,这些请求将“挂起”并且不符合垃圾回收的条件。

代码语言:javascript
复制
function clientErrorHandler (err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' })
  } else {
    next(err)
  }
}

“catch-all” 功能可能由errorHandler实现,如下:

代码语言:javascript
复制
function errorHandler (err, req, res, next) {
  res.status(500)
  res.render('error', { error: err })
}

如果您向next()函数传递任何东西(字符串'route'除外),则Express将当前请求视为错误,并且将跳过任何剩余的非错误处理路由和中间件函数。如果您想以某种方式处理该错误,则必须按照下一节中的描述创建错误处理路由。

如果您有一个具有多个回调函数的路由处理程序,则可以使用该route参数跳转到下一个路径处理程序。例如:

代码语言:javascript
复制
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中的默认错误处理机制:

代码语言:javascript
复制
function errorHandler (err, req, res, next) {
  if (res.headersSent) {
    return next(err)
  }
  res.status(500)
  res.render('error', { error: err })
}

请注意,如果您多次调用next()代码中的错误,即使自定义错误处理中间件已就位,也可以触发默认错误处理程序。

扫码关注腾讯云开发者

领取腾讯云代金券