在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 })