這個翻譯StrongLoop / IBM提供.

相對於英文版說明文件,本文件可能已不合時宜。如需最新的更新,請參閱英文版說明文件

錯誤處理

錯誤處理中介軟體函數的定義方式,與其他中介軟體函數相同,差別在於錯誤處理函數的引數是四個而非三個:(err, req, res, next)。例如:

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

您是在定義其他 app.use() 和路由呼叫之後,最後才定義錯誤處理中介軟體;例如:

const bodyParser = require('body-parser')
const methodOverride = require('method-override')

app.use(bodyParser())
app.use(methodOverride())
app.use((err, req, res, next) => {
  // logic
})

中介軟體函數內的回應可以是任何您喜好的格式,如:HTML 錯誤頁面、簡式訊息或 JSON 字串。

為了方便組織(和更高層次的架構),您可以定義數個錯誤處理中介軟體函數,就像您處理一般中介軟體函數一樣。舉例來說,如果您想為使用及沒有使用 XHR 所建立的要求,各定義一個錯誤處理程式,您可以使用下列指令:

const bodyParser = require('body-parser')
const methodOverride = require('method-override')

app.use(bodyParser())
app.use(methodOverride())
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)

在本例中,通用的 logErrors 可能將要求和錯誤資訊寫入至 stderr,例如:

function logErrors (err, req, res, next) {
  console.error(err.stack)
  next(err)
}

此外在本例中,clientErrorHandler 定義成如下;在此情況下,會將錯誤明確傳遞給下一個:

function clientErrorHandler (err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' })
  } else {
    next(err)
  }
}

“catch-all” errorHandler 函數的實作方式如下:

function errorHandler (err, req, res, next) {
  res.status(500)
  res.render('error', { error: err })
}

不論您傳遞何者給 next() 函數('route' 字串除外),Express 都會將現行要求視為發生錯誤,且會跳過其餘任何的非錯誤處理路由和中介軟體函數。如果您想以某種方式來處理該錯誤,您必須按照下一節的說明來建立錯誤處理路由。

如果您的路由處理程式有多個回呼函數,可以使用 route 參數來跳到下一個路由處理程式。例如:

app.get('/a_route_behind_paywall',
  (req, res, next) => {
    if (!req.user.hasPaid) {

      // continue handling this request
      next('route')
    }
  }, (req, res, next) => {
    PaidContent.find((err, doc) => {
      if (err) return next(err)
      res.json(doc)
    })
  })

在本例中,會跳過 getPaidContent 處理程式,但是會繼續執行 app/a_route_behind_paywall 的其餘處理程式。

呼叫 next()next(err),指出現行處理程式已完成以及處於何種狀態。除了依上述說明設定成用來處理錯誤的那些處理程式,next(err) 會跳過處理程式鏈中其餘所有的處理程式。</div>

預設錯誤處理程式

Express 隨附一個內建錯誤處理常式,它會處理應用程式中可能遇到的任何錯誤。這個預設錯誤處理中介軟體函數新增於中介軟體函數堆疊尾端。

如果您傳遞錯誤至 next(),且您沒有在錯誤處理常式中處理它,將會交由內建錯誤處理常式處理;該錯誤會連同堆疊追蹤寫入至用戶端。在正式作業環境中,則不包含堆疊追蹤。

NODE_ENV 環境變數設為 production,以便在正式作業模式下執行應用程式。

在您開始撰寫回應之後,一旦在呼叫 next() 時才發生錯誤(例如,當您將回應串流輸出至用戶端時遇到錯誤),Express 的預設錯誤處理程式會關閉連線,並使要求失敗。

因此,在您新增自訂錯誤處理常式時,如果標頭已傳送給用戶端,您會希望委派給 Express 中的預設錯誤處理機制處理:

function errorHandler (err, req, res, next) {
  if (res.headersSent) {
    return next(err)
  }
  res.status(500)
  res.render('error', { error: err })
}