?
This document uses PHP Chinese website manual Release
以與其他中間件功能相同的方式定義錯(cuò)誤處理中間件函數(shù),但錯(cuò)誤處理函數(shù)有四個(gè)參數(shù)而不是三個(gè):(err, req, res, next)
。例如:
app.use(function (err, req, res, next) { console.error(err.stack) res.status(500).send('Something broke!')})
您最后定義錯(cuò)誤處理中間件,在其他app.use()
路由之后并路由呼叫; 例如:
var bodyParser = require('body-parser') var methodOverride = require('method-override') app.use(bodyParser.urlencoded({ extended: true})) app.use(bodyParser.json()) app.use(methodOverride()) app.use(function (err, req, res, next) { // logic})
來自中間件功能的響應(yīng)可以采用任何您喜歡的格式,例如HTML錯(cuò)誤頁面,簡(jiǎn)單消息或JSON字符串。
對(duì)于組織(和更高級(jí)別的框架)目的,您可以定義幾個(gè)錯(cuò)誤處理中間件函數(shù),就像使用常規(guī)中間件函數(shù)一樣。例如,如果您想要為使用XHR
和不使用的請(qǐng)求定義錯(cuò)誤處理程序,則可以使用以下命令:
var bodyParser = require('body-parser') var methodOverride = require('method-override') app.use(bodyParser.urlencoded({ extended: true})) app.use(bodyParser.json()) app.use(methodOverride()) app.use(logErrors) app.use(clientErrorHandler) app.use(errorHandler)
在這個(gè)例子中,泛型logErrors
可能會(huì)給stderr
寫請(qǐng)求和錯(cuò)誤信息,例如:
function logErrors (err, req, res, next) { console.error(err.stack) next(err)}
同樣在這個(gè)例子中,clientErrorHandler
定義如下:在這種情況下,錯(cuò)誤會(huì)顯式傳遞給下一個(gè)錯(cuò)誤。
請(qǐng)注意,如果不在錯(cuò)誤處理函數(shù)中調(diào)用“next”,則需要負(fù)責(zé)編寫(并結(jié)束)響應(yīng)。否則,這些請(qǐng)求將“掛起”并且不符合垃圾回收的條件。
function clientErrorHandler (err, req, res, next) { if (req.xhr) { res.status(500).send({ error: 'Something failed!' }) } else { next(err) }}
“catch-all” 功能可能由errorHandler
實(shí)現(xiàn),如下:
function errorHandler (err, req, res, next) { res.status(500) res.render('error', { error: err })}
如果您向next()
函數(shù)傳遞任何東西(字符串'route'
除外),則Express將當(dāng)前請(qǐng)求視為錯(cuò)誤,并且將跳過任何剩余的非錯(cuò)誤處理路由和中間件函數(shù)。如果您想以某種方式處理該錯(cuò)誤,則必須按照下一節(jié)中的描述創(chuàng)建錯(cuò)誤處理路由。
如果您有一個(gè)具有多個(gè)回調(diào)函數(shù)的路由處理程序,則可以使用該route
參數(shù)跳轉(zhuǎn)到下一個(gè)路徑處理程序。例如:
app.get('/a_route_behind_paywall', function checkIfPaidSubscriber (req, res, next) { if (!req.user.hasPaid) { // continue handling this request next('route') }else{ next(); } }, function getPaidContent (req, res, next) { PaidContent.find(function (err, doc) { if (err) return next(err) res.json(doc) }) })
在這個(gè)例子中,getPaidContent
處理程序?qū)⒈惶^,但在任何剩余處理app時(shí)將
繼續(xù)要執(zhí)行/a_route_behind_paywall
。
調(diào)用next()
和next(err)
指出當(dāng)前處理程序已完成并處于何種狀態(tài)。next(err)
將會(huì)跳過鏈中所有剩余的處理程序,除了那些設(shè)置為處理錯(cuò)誤的處理程序,如上所述。
Express帶有一個(gè)內(nèi)置的錯(cuò)誤處理程序,它處理應(yīng)用程序中可能遇到的任何錯(cuò)誤。這個(gè)默認(rèn)的錯(cuò)誤處理中間件功能被添加到中間件功能堆棧的末尾。
如果你傳遞一個(gè)錯(cuò)誤next()
并且你沒有在錯(cuò)誤處理器中處理它,它將由內(nèi)置的錯(cuò)誤處理器來處理; 該錯(cuò)誤將通過堆棧跟蹤寫入客戶端。生產(chǎn)環(huán)境中不包含堆棧跟蹤。
為production
設(shè)置環(huán)境變量ODE_ENV
,運(yùn)行在生產(chǎn)模式下的應(yīng)用程序。
如果您調(diào)用next()
響應(yīng)后發(fā)生錯(cuò)誤(例如,如果在將響應(yīng)傳輸?shù)娇蛻舳藭r(shí)遇到錯(cuò)誤),Express默認(rèn)錯(cuò)誤處理程序?qū)㈥P(guān)閉連接并使請(qǐng)求失敗。
因此,當(dāng)您添加自定義錯(cuò)誤處理程序時(shí),您將希望在頭文件已經(jīng)發(fā)送到客戶端時(shí)委派到Express中的默認(rèn)錯(cuò)誤處理機(jī)制:
function errorHandler (err, req, res, next) { if (res.headersSent) { return next(err) } res.status(500) res.render('error', { error: err })}
請(qǐng)注意,如果您多次調(diào)用next()
代碼中的錯(cuò)誤,即使自定義錯(cuò)誤處理中間件已就位,也可以觸發(fā)默認(rèn)錯(cuò)誤處理程序。