?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
以與其他中間件功能相同的方式定義錯誤處理中間件函數(shù),但錯誤處理函數(shù)有四個參數(shù)而不是三個:(err, req, res, next)
。例如:
app.use(function (err, req, res, next) { console.error(err.stack) res.status(500).send('Something broke!')})
您最后定義錯誤處理中間件,在其他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錯誤頁面,簡單消息或JSON字符串。
對于組織(和更高級別的框架)目的,您可以定義幾個錯誤處理中間件函數(shù),就像使用常規(guī)中間件函數(shù)一樣。例如,如果您想要為使用XHR
和不使用的請求定義錯誤處理程序,則可以使用以下命令:
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)
在這個例子中,泛型logErrors
可能會給stderr
寫請求和錯誤信息,例如:
function logErrors (err, req, res, next) { console.error(err.stack) next(err)}
同樣在這個例子中,clientErrorHandler
定義如下:在這種情況下,錯誤會顯式傳遞給下一個錯誤。
請注意,如果不在錯誤處理函數(shù)中調(diào)用“next”,則需要負(fù)責(zé)編寫(并結(jié)束)響應(yī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)前請求視為錯誤,并且將跳過任何剩余的非錯誤處理路由和中間件函數(shù)。如果您想以某種方式處理該錯誤,則必須按照下一節(jié)中的描述創(chuàng)建錯誤處理路由。
如果您有一個具有多個回調(diào)函數(shù)的路由處理程序,則可以使用該route
參數(shù)跳轉(zhuǎn)到下一個路徑處理程序。例如:
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) }) })
在這個例子中,getPaidContent
處理程序?qū)⒈惶^,但在任何剩余處理app時(shí)將
繼續(xù)要執(zhí)行/a_route_behind_paywall
。
調(diào)用next()
和next(err)
指出當(dāng)前處理程序已完成并處于何種狀態(tài)。next(err)
將會跳過鏈中所有剩余的處理程序,除了那些設(shè)置為處理錯誤的處理程序,如上所述。
Express帶有一個內(nèi)置的錯誤處理程序,它處理應(yīng)用程序中可能遇到的任何錯誤。這個默認(rèn)的錯誤處理中間件功能被添加到中間件功能堆棧的末尾。
如果你傳遞一個錯誤next()
并且你沒有在錯誤處理器中處理它,它將由內(nèi)置的錯誤處理器來處理; 該錯誤將通過堆棧跟蹤寫入客戶端。生產(chǎn)環(huán)境中不包含堆棧跟蹤。
為production
設(shè)置環(huán)境變量ODE_ENV
,運(yùn)行在生產(chǎn)模式下的應(yīng)用程序。
如果您調(diào)用next()
響應(yīng)后發(fā)生錯誤(例如,如果在將響應(yīng)傳輸?shù)娇蛻舳藭r(shí)遇到錯誤),Express默認(rèn)錯誤處理程序?qū)㈥P(guān)閉連接并使請求失敗。
因此,當(dāng)您添加自定義錯誤處理程序時(shí),您將希望在頭文件已經(jīng)發(fā)送到客戶端時(shí)委派到Express中的默認(rèn)錯誤處理機(jī)制:
function errorHandler (err, req, res, next) { if (res.headersSent) { return next(err) } res.status(500) res.render('error', { error: err })}
請注意,如果您多次調(diào)用next()
代碼中的錯誤,即使自定義錯誤處理中間件已就位,也可以觸發(fā)默認(rèn)錯誤處理程序。