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

        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號
        主站蜘蛛池模板: 国产精品天天看天天狠| 国产精品无码专区在线观看| 亚洲日本精品一区二区| 亚洲精品卡2卡3卡4卡5卡区| 日韩欧国产精品一区综合无码| 正在播放酒店精品少妇约| 国产免费久久精品99久久| 亚洲国产成人久久精品动漫 | 国产成人精品无码片区在线观看| 久久亚洲中文字幕精品一区| 成人国产精品日本在线观看| 免费看一级毛片在线观看精品视频 | 亚洲第一精品福利| 99re国产精品视频首页| 国产精品v片在线观看不卡 | 国产精品国产三级专区第1集| 久久精品无码午夜福利理论片| 亚洲精品专区在线观看| 久久99精品国产麻豆不卡| 国产日韩精品无码区免费专区国产| 欧美精品一区二区三区视频| 国产精品欧美亚洲韩国日本| 国产成人亚洲合集青青草原精品 | 欧美人与性动交α欧美精品| 91精品国产91久久| 亚洲综合精品一二三区在线| 日韩精品在线观看视频| 四虎国产精品永久在线看| 国产精品电影在线观看| 免费视频成人国产精品网站| 99精品国产高清一区二区麻豆| 亚洲精品无码专区2| 欧美精品一二区| 国产在线观看高清精品| 国产精品视频色视频| 国产精品久久久久久久久久免费| 久久99精品国产99久久| 久久久久久久99精品免费观看| 99久久精品费精品国产一区二区| 91精品国产福利尤物| 97精品国产手机|