首頁技術(shù)文章正文

Express中間件的調(diào)用流程和常規(guī)操作,5分鐘了解

更新時(shí)間:2022-10-13 來源:黑馬程序員 瀏覽量:

中間件(Middleware ),特指業(yè)務(wù)流程的中間處理環(huán)節(jié)。例如工廠要排放生產(chǎn)中產(chǎn)生的污水,就必須要先將污水凈化以達(dá)到排放標(biāo)準(zhǔn)你,處理污水的時(shí)候,經(jīng)過的三個(gè)處理環(huán)節(jié),就可以叫做中間件。

1665643698803_中間件.png

Express 中間件的概念

Express 的中間件,本質(zhì)上就是一個(gè) function 處理函數(shù), 中間件函數(shù)的形參列表中,必須包含 next 參數(shù)。而路由處理函數(shù)中只包含 req 和 resExpress ,中間件的格式如下:

express中間件

next 函數(shù)是實(shí)現(xiàn)多個(gè)中間件連續(xù)調(diào)用的關(guān)鍵,它表示把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由。Express中間件從到響應(yīng)的流程如下:

1665644711078_5.png
下面我們來看Express中間件的幾種常規(guī)操作。

中間件常規(guī)操作

1. 定義中間件函數(shù)

可以通過如下的方式,定義一個(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()
}


2. 全局生效的中間件

客戶端發(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()
})

4. 中間件的作用

多個(gè)中間件之間,共享同一份req和res?;谶@樣的特性,我們可以在上游的中間件中,統(tǒng)一為req 或res 對象添加自定義的屬性或方法,供下游的中間件或路由進(jìn)行使用。

1665645930390_6.png

5. 定義多個(gè)全局中間件

可以使用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.')
})

6. 局部生效的中間件

不使用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.') })

7. 定義多個(gè)局部中間件

可以在路由中,通過如下兩種等價(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)置的中間件

⑤第三方的中間件

1. 應(yīng)用級別的中間件

通過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.')
})

2. 路由級別的中間件

綁定到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)

3. 錯(cuò)誤級別的中間件

錯(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ò)誤級別的中間件,必須注冊在所有路由之后!

4. Express內(nèi)置的中間件

自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 }))

5. 第三方的中間件

非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)一步封裝出來的。


分享到:
在線咨詢 我要報(bào)名
和我們在線交談!