站長資訊網
最全最豐富的資訊網站

nodejs中的中間件是什么意思

在nodejs中,中間件主要是指封裝所有Http請求細節處理的方法,是從Http請求發起到響應結束過程中的處理方法。中間件的行為比較類似Java中過濾器的工作原理,就是在進入具體的業務處理之前,先讓過濾器處理。

nodejs中的中間件是什么意思

本教程操作環境:windows7系統、nodejs 12.19.0版、Dell G3電腦。

中間件概念

在NodeJS中,中間件主要是指封裝所有Http請求細節處理的方法。一次Http請求通常包含很多工作,如記錄日志、ip過濾、查詢字符串、請求體解析、Cookie處理、權限驗證、參數驗證、異常處理等,但對于Web應用而言,并不希望接觸到這么多細節性的處理,因此引入中間件來簡化和隔離這些基礎設施與業務邏輯之間的細節,讓開發者能夠關注在業務的開發上,以達到提升開發效率的目的。

中間件的行為比較類似Java中過濾器的工作原理,就是在進入具體的業務處理之前,先讓過濾器處理。它的工作模型下圖所示。

nodejs中的中間件是什么意思

                    中間件工作模型

中間件機制核心實現

中間件是從Http請求發起到響應結束過程中的處理方法,通常需要對請求和響應進行處理,因此一個基本的中間件的形式如下:

const middleware = (req, res, next) => {   // TODO   next() }

以下通過兩種方式的中間件機制的實現來理解中間件是如何工作的。

方式一

如下定義三個簡單的中間件:

const middleware1 = (req, res, next) => {   console.log('middleware1 start')   next() }  const middleware2 = (req, res, next) => {   console.log('middleware2 start')   next() }  const middleware3 = (req, res, next) => {   console.log('middleware3 start')   next() }
// 中間件數組 const middlewares = [middleware1, middleware2, middleware3] function run (req, res) {   const next = () => {     // 獲取中間件數組中第一個中間件     const middleware = middlewares.shift()     if (middleware) {       middleware(req, res, next)     }   }   next() } run() // 模擬一次請求發起

執行以上代碼,可以看到如下結果:

middleware1 start middleware2 start middleware3 start

如果中間件中有異步操作,需要在異步操作的流程結束后再調用next()方法,否則中間件不能按順序執行。改寫middleware2中間件:

const middleware2 = (req, res, next) => {   console.log('middleware2 start')  new Promise(resolve => {     setTimeout(() => resolve(), 1000)   }).then(() => {     next()   }) }

執行結果與之前一致,不過middleware3會在middleware2異步完成后執行。

middleware1 start middleware2 start middleware3 start

有些中間件不止需要在業務處理前執行,還需要在業務處理后執行,比如統計時間的日志中間件。在方式一情況下,無法在next()為異步操作時再將當前中間件的其他代碼作為回調執行。因此可以將next()方法的后續操作封裝成一個Promise對象,中間件內部就可以使用next.then()形式完成業務處理結束后的回調。改寫run()方法如下:

function run (req, res) {   const next = () => {     const middleware = middlewares.shift()    if (middleware) {      // 將middleware(req, res, next)包裝為Promise對象       return Promise.resolve(middleware(req, res, next))     }   }   next() }

中間件的調用方式需改寫為:

const middleware1 = (req, res, next) => {   console.log('middleware1 start')  // 所有的中間件都應返回一個Promise對象   // Promise.resolve()方法接收中間件返回的Promise對象,供下層中間件異步控制   return next().then(() => {     console.log('middleware1 end')   }) }
const middleware1 = (req, res, next) => {     console.log('middleware1 start')    // 所有的中間件都應返回一個Promise對象     // Promise.resolve()方法接收中間件返回的Promise對象,供下層中間件異步控制     return next().then((res) => {       console.log("1",res)      return 'middleware1 end';     })   }      const middleware2 = (req, res, next) => {     console.log('middleware2 start')    // 所有的中間件都應返回一個Promise對象     // Promise.resolve()方法接收中間件返回的Promise對象,供下層中間件異步控制     // console.log("next()",next())     return next().then((res) => {       console.log("2",res)      return 'middleware2 end'     })   }   const middleware3 = (req, res, next) => {     console.log('middleware3 start')    return next().then((res) => {       console.log("3",res)      return 'middleware3 end'     })   }  const middlewares = [middleware1, middleware2, middleware3]function run (req, res) {     const next = () => {       const middleware = middlewares.shift()      if (middleware) {        //   console.log("next",next)         // 將middleware(req, res, next)包裝為Promise對象         return Promise.resolve(middleware(req, res, next))       }else {        return Promise.resolve("結束");       }     }     next()   } run() // 模擬一次請求發起

結果:

nodejs中的中間件是什么意思

async await 實現

const middleware1 = async (req, res, next) => {     console.log('middleware1 start')     let result = await next();     console.log("1",result)   }      const middleware2 = async (req, res, next) => {     console.log('middleware2 start')     let result = await next();     console.log("2",result)     return 'middleware2 end';   }   const middleware3 = async (req, res, next) => {     console.log('middleware3 start')     let result = await next();     console.log("3",result)     return 'middleware3 end';   }  const middlewares = [middleware1, middleware2, middleware3]  function run (req, res) {     const next = () => {       const middleware = middlewares.shift()       if (middleware) {         //   console.log("next",next)         // 將middleware(req, res, next)包裝為Promise對象         return Promise.resolve(middleware(req, res, next))       }else {         return Promise.resolve("結束");       }     }     next()   } run() // 模擬一次請求發起

nodejs中的中間件是什么意思

以上描述了中間件機制中多個異步中間件的調用流程,實際中間件機制的實現還需要考慮異常處理、路由等。

express框架中,中間件的實現方式為方式一,并且全局中間件和內置路由中間件中根據請求路徑定義的中間件共同作用,不過無法在業務處理結束后再調用當前中間件中的代碼。koa2框架中中間件的實現方式為方式二,將next()方法返回值封裝成一個Promise,便于后續中間件的異步流程控制,實現了koa2框架提出的洋蔥圈模型,即每一層中間件相當于一個球面,當貫穿整個模型時,實際上每一個球面會穿透兩次。

nodejs中的中間件是什么意思

koa2中間件洋蔥圈模型

koa2框架的中間件機制實現得非常簡潔和優雅,這里學習一下框架中組合多個中間件的核心代碼。

function compose (middleware) {   if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')   for (const fn of middleware) {     if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')   }   return function (context, next) {     let index = -1     return dispatch(0)     function dispatch (i) {       // index會在next()方法調用后累加,防止next()方法重復調用       if (i <= index) return Promise.reject(new Error('next() called multiple times'))       index = i       let fn = middleware[i]       if (i === middleware.length) fn = next       if (!fn) return Promise.resolve()       try {         // 核心代碼         // 包裝next()方法返回值為Promise對象         return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));       } catch (err) {         // 遇到異常中斷后續中間件的調用         return Promise.reject(err)       }     }   } }

koa中間件列表地址:https://github.com/koajs/koa/wiki

總結

本文主要介紹了中間件的概念、為何引入中間件以及中間件機制的核心實現。中間件機制使得Web應用具備良好的可擴展性和組合性。

在實現中間件時,單個中間件應該足夠簡單,職責單一。由于每個請求都會調用中間件相關代碼,中間件的代碼應該高效,必要的時候可以緩存重復獲取的數據。在對不同的路由使用中間件時,還應該考慮到不同的中間件應用到不同的路由上。

【推薦學習:《nodejs 教程》】

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
精品一区二区三区电影| 成人久久伊人精品伊人| 久久精品国产精品亚洲艾草网| 伊人久久精品影院| 日韩高清国产一区在线| 国产精品青草久久| 欧美日韩亚洲精品| 国产午夜精品片一区二区三区| 91精品国产免费入口| 亚洲2022国产成人精品无码区| 丰满人妻熟妇乱又伦精品| 精品一区二区三区高清免费观看| 日韩人妻无码免费视频一区二区三区| 国产AV一区二区精品凹凸| 国产精品成人一区无码| 精品一区狼人国产在线| 日产精品卡一卡二卡三的概述| 亚洲精品伊人久久久久| 91久久精品午夜一区二区| 99久在线精品99re6视频| 久久se精品一区二区国产| 久久777国产线看观看精品| 正在播放国产精品每日更新| 三级精品在线观看| AV无码精品一区二区三区宅噜噜| 国产精品龙口护士门在线观看 | 老司机精品视频免费| 日韩电影免费在线| 日韩精品一区二区三区国语自制| 中文字幕日韩一区| 日韩av无码成人无码免费| 日韩高清在线播放| 日韩a级一片在线观看| 日韩一区二区三区不卡视频| 精品视频一区二区观看| selao久久国产精品| 亚洲国产91精品无码专区| 国产叼嘿久久精品久久| 国产精品尹人在线观看| 久久这里有精品视频| 自拍中文精品无码|