更新時(shí)間:2023年09月12日11時(shí)27分 來源:傳智教育 瀏覽次數(shù):
中間件(Middleware ),特指業(yè)務(wù)流程的中間處理環(huán)節(jié)。例如工廠要排放生產(chǎn)中產(chǎn)生的污水,就必須要先將污水凈化以達(dá)到排放標(biāo)準(zhǔn)你,處理污水的時(shí)候,經(jīng)過的三個(gè)處理環(huán)節(jié),就可以叫做中間件。
Express 的中間件,本質(zhì)上就是一個(gè) function 處理函數(shù), 中間件函數(shù)的形參列表中,必須包含 next 參數(shù)。而路由處理函數(shù)中只包含 req 和 resExpress ,中間件的格式如下:
next 函數(shù)是實(shí)現(xiàn)多個(gè)中間件連續(xù)調(diào)用的關(guān)鍵,它表示把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由。Express中間件從到響應(yīng)的流程如下:
下面我們來看Express中間件的幾種常規(guī)操作。
可以通過如下的方式,定義一個(gè)最簡單的中間件函數(shù):
//常量mw所指向的,就是一個(gè)中間件函數(shù) const mw = function (req, res, next){ console.log('這是一個(gè)最簡單的中間件函數(shù)') //注意:在當(dāng)前中間件的業(yè)務(wù)處理完畢后,必須調(diào)用 next()函數(shù) //表示把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由 next() }
客戶端發(fā)起的任何請求,到達(dá)服務(wù)器之后,都會(huì)觸發(fā)的中間件,叫做全局生效的中間件。 通過調(diào)用app.use(中間件函數(shù)),即可定義一個(gè)全局生效的中間件,全局生效中間件的示例代碼如下:
//常量mw所指向的,就是一個(gè)中間件函數(shù) const mw = function (req, res, next) { console.log('這是一個(gè)最簡單的中間件函數(shù)’) next() } //全局生效的中間件 app.use(mw)
3. 定義全局中間件的簡化形式
定義全局中間件的簡化形式可以參考如下代碼:
//全局生效的中間件 app.use(function (req, res, next) { console.log(’這是一個(gè)最簡單的中間件函數(shù)’) next() })
多個(gè)中間件之間,共享同一份req和res?;谶@樣的特性,我們可以在上游的中間件中,統(tǒng)一為req 或res 對象添加自定義的屬性或方法,供下游的中間件或路由進(jìn)行使用。
可以使用app.use() 連續(xù)定義多個(gè)全局中間件。客戶端請求到達(dá)服務(wù)器之后,會(huì)按照中間件定義的先后順序依次進(jìn)行調(diào)用,示例代碼如下:
app.use(function(req,res,next){//第1個(gè)全局中間件 console.log('調(diào)用了第1個(gè)全局中間件') next() }) app.use(function(req,res,next){//第2個(gè)全局中間件 console.log('調(diào)用了第2個(gè)全局中間件') next() 1}) app.get('/user',(req,res)=>{//請求這個(gè)路由,會(huì)依次觸發(fā)上述兩個(gè)全局中間件 res.send('Home page.') })
不使用app.use() 定義的中間件,叫做局部生效的中間件,示例代碼如下:
//定義中間件函數(shù)mw1 const mw1 = function(req, res, next) ( cosole.log('這是中間件函數(shù)') next() } //mN1 這個(gè)中間件只在“當(dāng)前路由中生效”,這種用法屬于“局部生效的中間件” app.get('/',mwi,function(req,res){ res.send('Home page.') }) //mw1這個(gè)中間件不會(huì)影響下面這個(gè)路由!+ app.get('/user', function(req, res) { res.send('User page.') })
可以在路由中,通過如下兩種等價(jià)的方式,使用多個(gè)局部中間件:
//以下兩種寫法是“完全等價(jià)“的,可根據(jù)自己的喜好,選擇任意一種方式進(jìn)行使用 apg.get('/',mw1,mw2,(req,res)=>{res.send('Home page.')}) app.get('/',[mw1,mw2],(req,res)=>{ res.send('Home page.') })
注意:一定要在路由之前注冊中間件,客戶端發(fā)送過來的請求,可以連續(xù)調(diào)用多個(gè)中間件進(jìn)行處理。執(zhí)行完中間件的業(yè)務(wù)代碼之后,不要忘記調(diào)用next() 函數(shù)。為了防止代碼邏輯混亂,調(diào)用next() 函數(shù)后不要再寫額外的代碼。連續(xù)調(diào)用多個(gè)中間件時(shí),多個(gè)中間件之間,共享req 和res 對象。
為了方便大家理解和記憶中間件的使用,Express 官方把常見的中間件用法,分成了5 大類,分別是:
①應(yīng)用級別的中間件
②路由級別的中間件
③錯(cuò)誤級別的中間件
④Express 內(nèi)置的中間件
⑤第三方的中間件
通過app.use() 或app.get() 或app.post() ,綁定到app 實(shí)例上的中間件,叫做應(yīng)用級別的中間件,代碼示例如下:
//應(yīng)用級別的中間件(全局中間件) app.use((req,res,next)=>{ next() }) //應(yīng)用級別的中間件(局部中間件) app.get('/',mwi,(req, res) =>{ res.send('Home page.') })
綁定到express.Router() 實(shí)例上的中間件,叫做路由級別的中間件。它的用法和應(yīng)用級別中間件沒有任何區(qū)別。只不過,應(yīng)用級別中間件是綁定到app 實(shí)例上,路由級別中間件綁定到router 實(shí)例上,代碼示例如下:
var app = express() var router = express.Router( //路由級別的中間件 router.use(function (req, res, next) ( console.log('Time:', Date.now()) next() }) app.use('/', router)
錯(cuò)誤級別中間件的作用:專門用來捕獲整個(gè)項(xiàng)目中發(fā)生的異常錯(cuò)誤,從而防止項(xiàng)目異常崩潰的問題。
格式:錯(cuò)誤級別中間件的function 處理函數(shù)中,必須有4 個(gè)形參,形參順序從前到后,分別是(err, req, res, next)。
app.get('/', function (req, res){ // 1.路由 throw new Error('服務(wù)器內(nèi)部發(fā)生了錯(cuò)誤!') // 1.1拋出一個(gè)自定義的錯(cuò)誤 res.send('Home Page.') }) app.use(function(err,req,res,next){ // 2.錯(cuò)誤級別的中間件 console.log('發(fā)生了錯(cuò)誤:'+err.message) //2.1在服務(wù)器打印錯(cuò)誤消息 res.send('Error!'+ err.message) //2.2向客戶端響應(yīng)錯(cuò)誤相關(guān)的內(nèi)容 })
注意:錯(cuò)誤級別的中間件,必須注冊在所有路由之后!
自Express 4.16.0 版本開始,Express 內(nèi)置了3 個(gè)常用的中間件,極大的提高了Express 項(xiàng)目的開發(fā)效率和體驗(yàn):
①express.static快速托管靜態(tài)資源的內(nèi)置中間件,例如:HTML 文件、圖片、CSS 樣式等(無兼容性)
②express.json解析JSON 格式的請求體數(shù)據(jù)(有兼容性,僅在4.16.0+ 版本中可用)
③express.urlencoded解析URL-encoded 格式的請求體數(shù)據(jù)(有兼容性,僅在4.16.0+ 版本中可用)
//配置解析 application/json 格式數(shù)據(jù)的內(nèi)置中間件 app.use(express.json()) //配置解析 application/x-ww-form-urlencoded 格式數(shù)據(jù)的內(nèi)置中間件 app.us(express.urlencoded({ extended:false }))
非Express 官方內(nèi)置的,而是由第三方開發(fā)出來的中間件,叫做第三方中間件。在項(xiàng)目中,大家可以按需下載并配置第三方中間件,從而提高項(xiàng)目的開發(fā)效率。
例如:在express@4.16.0 之前的版本中,經(jīng)常使用body-parser 這個(gè)第三方中間件,來解析請求體數(shù)據(jù)。使用步驟如下:
①運(yùn)行npm install body-parser安裝中間件
②使用require導(dǎo)入中間件
③調(diào)用app.use() 注冊并使用中間件
注意:Express 內(nèi)置的express.urlencoded中間件,就是基于body-parser 這個(gè)第三方中間件進(jìn)一步封裝出來的。
北京校區(qū)