淺析Node中Express的錯誤處理中介軟體

2022-04-06 22:00:22
本篇文章帶大家瞭解一下中Express的錯誤處理中介軟體,介紹一下定義錯誤處理中介軟體、與 async/await 一起使用的方法,希望對大家有所幫助!

Express 的錯誤處理中介軟體可幫助您處理錯誤,而無需重複同樣的工作。假設您直接在 Express 路由處理程式中處理錯誤:

app.put('/user/:id', async (req, res) => {
  let user
  try {
    user = await User.findOneAndUpdate({ _id: req.params.id }, req.body)
  } catch (err) {
    return res.status(err.status || 500).json({ message: err.message })
  }
  return res.json({ user })
})

上面的程式碼可以正常工作,但是,如果有數百個介面呢,那麼錯誤處理邏輯將變得不可維護,因為它被重複了數百次。

定義錯誤處理中介軟體

Express 根據中介軟體函數採用的引數數量分為不同的型別。接受 4 個引數的中介軟體函數被定義為錯誤處理中介軟體,只有在發生錯誤時才會被呼叫。

const app = require('express')()

app.get('*', function routeHandler() {
  // 此中介軟體丟擲一個錯誤,Express 將直接轉到下一個錯誤處理程式
  throw new Error('Oops!')
})

app.get('*', (req, res, next) => {
  // 此中介軟體不是錯誤處理程式(只有3個引數),Express 將跳過它,因為之前的中介軟體中存在錯誤
  console.log('這裡不會列印')
})

// 您的函數必須接受 4 個引數,以便 Express 將其視為錯誤處理中介軟體。
app.use((err, req, res, next) => {
  res.status(500).json({ message: err.message })
})

Express 會自動為您處理同步錯誤,如上面的 routeHandler() 方法。但是 Express 不處理非同步錯誤。如果出現非同步錯誤,則需要呼叫 next()

const app = require('express')()

app.get('*', (req, res, next) => {
  // next() 方法告訴 Express 轉到鏈中的下一個中介軟體。
  // Express 不處理非同步錯誤,因此您需要通過呼叫 next() 來報告錯誤。
  setImmediate(() => {
    next(new Error('Oops'))
  })
})

app.use((err, req, res, next) => {
  res.status(500).json({
    message: err.message
  })
})

請記住,Express 中介軟體是按順序執行的。您應該在所有其他中介軟體之後,最後定義錯誤處理程式。否則,您的錯誤處理程式將不會被呼叫:

async/await 一起使用

Express 無法捕獲 promise 的異常,Express 在 ES6 之前編寫,對於如何處理 async/await 它扔沒有好的解決方案。

例如,下面的伺服器永遠不會成功傳送 HTTP 響應,因為 Promise reject 永遠不會得到處理:

const app = require('express')()

app.get('*', (req, res, next) => {
  // 報告非同步錯誤必須通過 next()
  return new Promise((resolve, reject) => {
    setImmediate(() => reject(new Error('woops')))
  }).catch(next)
})

app.use((error, req, res, next) => {
  console.log('will not print')
  res.json({ message: error.message })
})

app.listen(3000)

我們可以封裝或者使用現有的庫來進行捕獲。

首先,我們先簡單封裝一個函數,將 async/await 與 Express 錯誤處理中介軟體聯絡起來。

注意:非同步函數會返回 Promise,因此您需要確保 catch() 所有錯誤並將其傳遞給 next()

function wrapAsync(fn) {
  return function(req, res, next) {
    fn(req, res, next).catch(next)
  }
}

app.get('*', wrapAsync(async (req, res) => {
  await new Promise(resolve => setTimeout(() => resolve(), 50))
  // Async error!
  throw new Error('woops')
}))

使用第三方庫 express-async-errors,一個簡單的 ES6 async/await 支援 hack:

require('express-async-errors')
app.get('*', async (req, res, next) => {
  await new Promise((resolve) => setTimeout(() => resolve(), 50))
  throw new Error('woops')
})

最後

Express 錯誤處理中介軟體允許您以最大化關注點分離的方式處理錯誤。您不需要處理業務邏輯中的錯誤,如果使用 async/await,甚至不需要 try/catch。這些錯誤將出現在您的錯誤處理程式中,然後您的錯誤處理程式可以決定如何響應請求。確保在下一個 Express 應用程式中充分利用這一強大功能!

更多node相關知識,請存取:!

以上就是淺析Node中Express的錯誤處理中介軟體的詳細內容,更多請關注TW511.COM其它相關文章!