express错误处理中间件

893 阅读2分钟

在express框架,如果请求中遇到了异常错误,需要保证程序能正常执行且返回服务端错误500,不可以直接中断程序,这样程序才比较健全。因此需要一个错误处理中间件可以此类问题

1、错误处理中间件

错误处理中间件总是需要四个参数。有这四个参数的中间件,将默认为错误处理中间件函数。即使不需要使用next对象,也必须添加该参数。否则,该next对象将被解释为常规中间件并且无法处理错误。有关错误处理中间件的详细信息,请参阅:错误处理

以与其他中间件函数相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数,特别是使用签名(err, req, res, next)):

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

2、同步错误

如果是同步代码出现异常,会直接被错误中间件捕获,并且正常处理

app.get('/', (req, res) => {
  throw new Error('BROKEN') // Express will catch this on its own.
})

3、异步错误

  • 在项目中,由于代码中存在大量的异步处理,按照同步错误处理方式处理,错误没有被捕获,导致服务意外被终止,这个影响非常大。
  • 因此异步错误情况,需要特殊处理。使用next(error)来传递错误信息,就可以正常使用错误中间件
  • 处理情况:
    • 1、如果express 是5版本以上的话,只要路由处理函数,默认返回Promise对象,express会自动调用next返回错误信息,不需要额外处理
    • 2、可以使用try{}catch(error){next(error)},但是会存在多个使用try{}catch(){},太过于繁琐,此方法不建议使用
    app.get('/', async(req, res, next) => {
        try {
          await fn();
          next();
        } catch (error) {
          next(error)
        }
      }
    
    • 3、使用Promise.resolve().then().catch(next),通过catch进行捕获异常。
    app.get('/', (req, res, next) => {
      Promise.resolve().then(() => {
        throw new Error('BROKEN')
      }).catch(next) // Errors will be passed to Express.
    })
    
    • 4、由于我的express版本是4版本,基于第3点,重新封装一个处理路由处理函数的函数,其中fn是返回一个Promise对象。
    wrapAsync(fn) {
        return function(req, res, next) {
          fn(req, res, next).catch(next)
        }
      }
    

4、异步返回值

  • 中间件函数的响应可以是任何格式,例如 HTML 错误页面、简单消息或 JSON 字符串。
  • 需要设置服务端错误代码res.status(500)
res.status(500).send('Something broke!');
res.status(500).send({ error: 'Something failed!' });
res.status(500).render('error', { error: err })