如何处理Express异常?
异常 如何 处理 Express
2023-09-11 14:20:14 时间
译者按:根据墨菲定律:“有可能出错的事情,就会出错”。那么,既然代码必然会出错,我们就应该处理好异常。
为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。
处理异常是编程非常重要的一点。我们的程序依赖于第三方服务、数据库以及我们的用户,一切都不可预料。数据库可能会宕机,第三方服务可能会崩溃,用户可能会使用错误的参数调用我们的接口。
为了处理各种复杂的情况,我们必须处理好代码异常,下面是代码示例:
app.get('/users/:id', (req, res) => {
const userId = req.params.id
if (!userId) {
return res.sendStatus(400).json({
error: 'Missing id'
})
}
Users.get(userId, (err, user) => {
if (err) {
return res.sendStatus(500).json(err)
}
res.send(users)
})
})
代码中处理了异常,但是存在问题:
- 在多处代码处理异常
- 没有使用Express的异常处理模块来统一处理异常
接下来,我们来一步步优化代码异常处理。
Express异常处理中间件
所有Express的路由处理函数都有第三个参数next,它可以用来调用下一个中间件,也可以将错误传递给错误处理中间件:
app.get('/users/:id', (req, res, next) => {
const userId = req.params.id
if (!userId) {
const error = new Error('missing id')
error.httpStatusCode = 400
return next(error)
}
Users.get(userId, (err, user) => {
if (err) {
err.httpStatusCode = 500
return next(err)
}
res.send(users)
})
})
使用next(err),Express就知道出错了,并把这个错误传递给错误处理模块。为了处理这些错误,需要添加一个中间件,它有4个参数:
app.use((err, req, res, next) => {
// log the error...
res.sendStatus(err.httpStatusCode).json(err)
})
这样,我们就可以使用中间件统一处理错误了。但是,现在的代码有些重复:创建错误,指定HTTP状态码,使用next(err)...
Fundebug是全栈JavaScript错误监控平台,支持各种前端和后端框架,可以帮助您第一时间发现BUG!
boom
boom是一个兼容HTTP的错误对象,他提供了一些标准的HTTP错误,比如400(参数错误)等。
const boom = require('boom')
app.get('/users/:id', (req, res, next) => {
const userId = req.params.id
if (!userId) {
return next(boom.badRequest('missing id'))
}
Users.get(userId, (err, user) => {
if (err) {
return next(boom.badImplementation(err))
}
res.send(users)
})
})
错误处理中间件需要稍作修改:
app.use((err, req, res, next) => {
if (err.isServer) {
// log the error...
// probably you don't want to log unauthorized access
// or do you?
}
return res.status(err.output.statusCode).json(err.output.payload);
})
Async/Await错误处理
使用Async/Await之后,可以这样处理Express异常:
- 将中间件使用Promise封装起来,使用catch统一处理异常
- 在中间件中,直接抛出异常就可以了
const boom = require('boom');
// wrapper for our async route handlers
// probably you want to move it to a new file
const asyncMiddleware = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch((err) => {
if (!err.isBoom) {
return next(boom.badImplementation(err));
}
next(err);
});
};
// the async route handler
app.get('/users/:id', asyncMiddleware(async (req, res) => {
const userId = req.params.id
if (!userId) {
throw boom.badRequest('missing id')
}
const user = await Users.get(userId)
res.json(user)
}))
参考
版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/12/06/handle-express-error/
相关文章
- 如何解决C#异常:必须先将当前线程设置为单线程单元(STA)模式,然后才能进行OLE调用,请确保你的Main函数已在其上标记了STAThreadAttribute
- WebService如何抛出干净的异常
- C#异常处理
- 异常:javax.el.PropertyNotFoundException: Property 'id' not found on ..........
- Hibernate4.3在开发中的一些异常总结(持续更新)
- 异常:java.lang.RuntimeException: Canvas: trying to draw too large(161740800bytes) bitmap
- Spring AOP异常:Error creating bean with name ‘org.springframework.aop.aspectj.
- Atitit 增强代码健壮性 出错继续执行恢复模式,就像vbs那样我以为我可以使用Try/Catch,但是我找不到异常后是否可以继续执行代码,并且找不到如何在最后显示错误消息。目录PHP
- 如何处理TCPSocket客户端与服务器端连接中断后的异常
- 如何处理TCPSocket客户端与服务器端连接中断后的异常
- Java学习之路 之 异常总结篇
- 引发了未经处理的异常:读取访问权限冲突。 _First 是 nullptr。
- Java如何使用线程异常?
- Java数组超出范围时如何处理多个异常?
- 【异常】记一次因错误运用数据冗余,导致的数据不一致的生产事故
- 【前沿技术RPA】 万字吃透UiPath如何处理异常