译者按:根据墨菲定律:“有可能出错的事情,就会出错”。那么,既然代码必然会出错,咱们就应该处理好异常。javascript
为了保证可读性,本文采用意译而非直译。另外,本文版权归原做者全部,翻译仅用于学习。前端
处理异常是编程很是重要的一点。咱们的程序依赖于第三方服务、数据库以及咱们的用户,一切都不可预料。数据库可能会宕机,第三方服务可能会崩溃,用户可能会使用错误的参数调用咱们的接口。java
为了处理各类复杂的状况,咱们必须处理好代码异常,下面是代码示例:数据库
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
接下来,咱们来一步步优化代码异常处理。npm
全部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个参数:json
app.use((err, req, res, next) => { // log the error... res.sendStatus(err.httpStatusCode).json(err) })
这样,咱们就能够使用中间件统一处理错误了。可是,如今的代码有些重复:建立错误,指定HTTP状态码,使用next(err)...后端
Fundebug是全栈JavaScript错误监控平台,支持各类前端和后端框架,能够帮助您第一时间发现BUG!app
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以后,能够这样处理Express异常:
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/