Bug描述
使用抛出错误的方式来处理异常应该是非常常见的情况,在express中,可以使用四个参数err, req, res, next的中间件来处理错误
app.use((err, req, res, next) => {
// 处理错误
})
但是笔者在使用的中,发现这种方式处理不了异步方法中抛出的错误
app.get('/test', async (req, res) => {
const res = await querySomething()
if(!res) throw new Error('nothing find')
})
app.use((err, req, res, next) => {
// 接收不到错误
})
// 控制台报错
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
解决方式
笔者尝试在express框架上下手,但是没有找到可以处理异步错误的API(Tips:也有可能是笔者没有发现,如果小伙伴们发现有的话,可以告诉笔者),于是只能通过try catch将异步错误截获,最后再抛出,在全局的错误处理中就能够将其处理
const assert = require('http-assert') // 处理错误的插件
app.use(
'/api/admin/',
// token验证
async (req, res, next) => {
// 在try语句块中捕获异常
try {
assert(req.headers['authorized'], 401, 'token不存在,请先登录')
const token = req.headers['authorized'].split(' ').pop()
const payload = jwt.verify(token, app.get('SECRET_KEY'))
assert(payload, 401, 'token认证失败,请重新登录')
const obj = await require('../../models/Admin').findById(payload._id)
assert(obj, 401, '用户认证失败,请重新登录')
await next()
} catch (err) {
next(err) // 在这里重新抛出异常
}
}
)
app.use(async (err, req, res, next) => {
res.send(R.error(err.statusCode || 9999, err.message))
})