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