譯者按:根據墨菲定律:「有可能出錯的事情,就會出錯」。那麼,既然代碼必然會出錯,咱們就應該處理好異常。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/