溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

nodej中間件指的是什么意思

發(fā)布時(shí)間:2021-10-29 16:14:32 來(lái)源:億速云 閱讀:166 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要介紹了nodej中間件指的是什么意思,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

在nodejs中,中間件主要是指封裝所有Http請(qǐng)求細(xì)節(jié)處理的方法,是從Http請(qǐng)求發(fā)起到響應(yīng)結(jié)束過(guò)程中的處理方法。中間件的行為比較類似Java中過(guò)濾器的工作原理,就是在進(jìn)入具體的業(yè)務(wù)處理之前,先讓過(guò)濾器處理。

本教程操作環(huán)境:windows7系統(tǒng)、nodejs 12.19.0版、Dell G3電腦。

中間件概念

在NodeJS中,中間件主要是指封裝所有Http請(qǐng)求細(xì)節(jié)處理的方法。一次Http請(qǐng)求通常包含很多工作,如記錄日志、ip過(guò)濾、查詢字符串、請(qǐng)求體解析、Cookie處理、權(quán)限驗(yàn)證、參數(shù)驗(yàn)證、異常處理等,但對(duì)于Web應(yīng)用而言,并不希望接觸到這么多細(xì)節(jié)性的處理,因此引入中間件來(lái)簡(jiǎn)化和隔離這些基礎(chǔ)設(shè)施與業(yè)務(wù)邏輯之間的細(xì)節(jié),讓開(kāi)發(fā)者能夠關(guān)注在業(yè)務(wù)的開(kāi)發(fā)上,以達(dá)到提升開(kāi)發(fā)效率的目的。

中間件的行為比較類似Java中過(guò)濾器的工作原理,就是在進(jìn)入具體的業(yè)務(wù)處理之前,先讓過(guò)濾器處理。它的工作模型下圖所示。

nodej中間件指的是什么意思

                    中間件工作模型

中間件機(jī)制核心實(shí)現(xiàn)

中間件是從Http請(qǐng)求發(fā)起到響應(yīng)結(jié)束過(guò)程中的處理方法,通常需要對(duì)請(qǐng)求和響應(yīng)進(jìn)行處理,因此一個(gè)基本的中間件的形式如下:

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

以下通過(guò)兩種方式的中間件機(jī)制的實(shí)現(xiàn)來(lái)理解中間件是如何工作的。

方式一

如下定義三個(gè)簡(jiǎn)單的中間件:

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()
}
// 中間件數(shù)組
const middlewares = [middleware1, middleware2, middleware3]
function run (req, res) {
  const next = () => {
    // 獲取中間件數(shù)組中第一個(gè)中間件
    const middleware = middlewares.shift()
    if (middleware) {
      middleware(req, res, next)
    }
  }
  next()
}
run() // 模擬一次請(qǐng)求發(fā)起

執(zhí)行以上代碼,可以看到如下結(jié)果:

middleware1 start
middleware2 start
middleware3 start

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

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

執(zhí)行結(jié)果與之前一致,不過(guò)middleware3會(huì)在middleware2異步完成后執(zhí)行。

middleware1 start
middleware2 start
middleware3 start

有些中間件不止需要在業(yè)務(wù)處理前執(zhí)行,還需要在業(yè)務(wù)處理后執(zhí)行,比如統(tǒng)計(jì)時(shí)間的日志中間件。在方式一情況下,無(wú)法在next()為異步操作時(shí)再將當(dāng)前中間件的其他代碼作為回調(diào)執(zhí)行。因此可以將next()方法的后續(xù)操作封裝成一個(gè)Promise對(duì)象,中間件內(nèi)部就可以使用next.then()形式完成業(yè)務(wù)處理結(jié)束后的回調(diào)。改寫(xiě)run()方法如下:

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

中間件的調(diào)用方式需改寫(xiě)為:

const middleware1 = (req, res, next) => {
  console.log('middleware1 start')  // 所有的中間件都應(yīng)返回一個(gè)Promise對(duì)象
  // Promise.resolve()方法接收中間件返回的Promise對(duì)象,供下層中間件異步控制
  return next().then(() => {
    console.log('middleware1 end')
  })
}
const middleware1 = (req, res, next) => {
    console.log('middleware1 start')    // 所有的中間件都應(yīng)返回一個(gè)Promise對(duì)象
    // Promise.resolve()方法接收中間件返回的Promise對(duì)象,供下層中間件異步控制
    return next().then((res) => {
      console.log("1",res)      return 'middleware1 end';
    })
  }
  
  const middleware2 = (req, res, next) => {
    console.log('middleware2 start')    // 所有的中間件都應(yīng)返回一個(gè)Promise對(duì)象
    // Promise.resolve()方法接收中間件返回的Promise對(duì)象,供下層中間件異步控制
    // 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對(duì)象
        return Promise.resolve(middleware(req, res, next))
      }else {        return Promise.resolve("結(jié)束");
      }
    }
    next()
  }
run() // 模擬一次請(qǐng)求發(fā)起

結(jié)果:

nodej中間件指的是什么意思

async await 實(shí)現(xiàn)

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對(duì)象
        return Promise.resolve(middleware(req, res, next))
      }else {
        return Promise.resolve("結(jié)束");
      }
    }
    next()
  }
run() // 模擬一次請(qǐng)求發(fā)起

nodej中間件指的是什么意思

以上描述了中間件機(jī)制中多個(gè)異步中間件的調(diào)用流程,實(shí)際中間件機(jī)制的實(shí)現(xiàn)還需要考慮異常處理、路由等。

express框架中,中間件的實(shí)現(xiàn)方式為方式一,并且全局中間件和內(nèi)置路由中間件中根據(jù)請(qǐng)求路徑定義的中間件共同作用,不過(guò)無(wú)法在業(yè)務(wù)處理結(jié)束后再調(diào)用當(dāng)前中間件中的代碼。koa2框架中中間件的實(shí)現(xiàn)方式為方式二,將next()方法返回值封裝成一個(gè)Promise,便于后續(xù)中間件的異步流程控制,實(shí)現(xiàn)了koa2框架提出的洋蔥圈模型,即每一層中間件相當(dāng)于一個(gè)球面,當(dāng)貫穿整個(gè)模型時(shí),實(shí)際上每一個(gè)球面會(huì)穿透兩次。

nodej中間件指的是什么意思

koa2中間件洋蔥圈模型

koa2框架的中間件機(jī)制實(shí)現(xiàn)得非常簡(jiǎn)潔和優(yōu)雅,這里學(xué)習(xí)一下框架中組合多個(gè)中間件的核心代碼。

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會(huì)在next()方法調(diào)用后累加,防止next()方法重復(fù)調(diào)用
      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對(duì)象
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
      } catch (err) {
        // 遇到異常中斷后續(xù)中間件的調(diào)用
        return Promise.reject(err)
      }
    }
  }
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“nodej中間件指的是什么意思”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI