最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

20行代碼簡單實現(xiàn)koa洋蔥圈模型示例詳解

 更新時間:2023年01月17日 10:01:26   作者:秋染蒹葭  
這篇文章主要為大家介紹了20行代碼簡單實現(xiàn)koa洋蔥圈模型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

koa想必很多人直接或間接的都用過,其源碼不知道閱讀本文的你有沒有看過,相當精煉,本文想具體說說koa的中間件模型,一起看看koa-compose的源碼,這也是koa系列的第一篇文章,后續(xù)會更新一下koa相關的其他知識點

koa中間件的使用

先讓我們啟動一個koa服務

// app.js
const koa = require('koa');
const app = new koa();
app.use(async (ctx, next) => {
  console.log('進入第一個中間件')
  next();
  console.log('退出第一個中間件')
})
app.use(async (ctx, next) => {
  console.log('進入第2個中間件')
  next();
  console.log('退出第2個中間件')
})
app.use((ctx, next) => {
  console.log('進入第3個中間件')
  next();
  console.log('退出第3個中間件')
})
app.use(ctx => {
  ctx.body = 'hello koa'
})
app.listen(8080, () => {
  console.log('服務啟動,監(jiān)聽8080端口')
})

上述的服務在訪問的時候會得到如下結(jié)果:

服務啟動,監(jiān)聽8080端口
進入第1個中間件
進入第2個中間件
進入第3個中間件
退出第3個中間件
退出第2個中間件
退出第1個中間件

上面的返回結(jié)果有點像一個遞歸的過程,從現(xiàn)象上看當中間件調(diào)用next()的時候,函數(shù)會暫停并進入到下一個中間件,當執(zhí)行了最后一個中間件后,執(zhí)行代碼會回溯上游中間件,并執(zhí)行next()之后的代碼,這就是koa的核心能力,洋蔥圈模型

洋蔥圈模型

先看一張經(jīng)典的洋蔥圈模型的示意圖:

在開發(fā)過程中,可以將next()之前的代碼理解為捕獲階段, 而next()之后的代碼可以理解為釋放階段,開發(fā)者結(jié)合這兩個狀態(tài)可以實現(xiàn)一些有趣的操作,比如記錄一次請求的時間:

async function responseTime(ctx, next) {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set('X-Response-Time', `${ms}ms`);
}
app.use(responseTime);

使用洋蔥圈模型可以直接將響應時間記錄的操作解耦出來,這樣就不需要再去對稱的寫在業(yè)務邏輯中了,這是怎么實現(xiàn)的呢?

洋蔥圈模型的實現(xiàn),koa-compose

我們通過app.use()添加了很多函數(shù),這些函數(shù)最終傳遞給了compose函數(shù),先貼上koa-compose的源碼,這里筆者刪除掉了校驗入?yún)⒌囊恍┓侵鞲蛇壿?,我們可以看到代碼也就十幾行,非常簡單,接下來讓我們一行一行的去看一下代碼

function compose (middleware) {
  // 返回一個匿名函數(shù),next為可選參數(shù)
  return function (context, next) {
    // 記錄當前執(zhí)行位置的游標
    let index = -1
    // 從第一個中間件開始,串起所有中間件
    return dispatch(0)
    function dispatch (i) {
      // 為了不破壞洋蔥圈模型,不允許在單個中間件中執(zhí)行多次next函數(shù)
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      // 更新游標
      index = i
      let fn = middleware[i]
      // 判斷邊界,假如已經(jīng)到到邊界了,可執(zhí)行外部傳入的回調(diào)
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
        // 核心處理邏輯,進入fn的執(zhí)行上下文的時候,dispatch就是通過綁定下一個index,變成了next,進入到下一個中間件
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
}

compose接收一個的函數(shù)數(shù)組[fn1, fn2, fn3, ...],compose調(diào)用后,返回了一個匿名函數(shù),匿名函數(shù)接收兩個參數(shù)

  • 第一個參數(shù)是上下文,對于koa的上下文不在本文的探究范圍,我們只要記得這個是在各個中間件中的共享的就可以了
  • 第二個參數(shù)標記為next,可選參數(shù),在中間件執(zhí)行的最后檢查執(zhí)行,這個和自定義的中間件中的next不完全一樣,一般是初始化返回了匿名函數(shù)后,調(diào)用方自己指定,用于處理一下默認邏輯

通過源碼可以看出,compose是提供了一個洋蔥模型完全執(zhí)行的回調(diào),通過把函數(shù)存儲起來,用next作為鑰匙,串起了我們所有的中間件,其核心代碼就是:

Promise.resolve(fn(context, dispatch.bind(null, i + 1)))

進入fn的執(zhí)行上下文的時候,dispatch就是通過綁定下一個index,變成了next,進入到下一個中間件。另外fn(中間件函數(shù))可以是個異步函數(shù),Promise.resolve會等到內(nèi)部異步函數(shù)resolve之后觸發(fā)

單次調(diào)用限制

假如在單個中間件中執(zhí)行多次next函數(shù)的話,會造成下游的中間件多次執(zhí)行,這樣就破壞了洋蔥圈模型,因此限制了在單個中間件中只能執(zhí)行一次next函數(shù),實現(xiàn)方式時在函數(shù)記錄了一個游標index,初始值是-1;這個游標會記錄當前執(zhí)行到哪個中間件,用來禁止在中間件中多次調(diào)用next函數(shù)

在一個中間件內(nèi)多次調(diào)用next的時候,你就會收到下面這個報錯

UnhandledPromiseRejectionWarning: Error: next() called multiple times

koa-compose與流程引擎

koa-compose不僅僅只是koa的一個依賴包,在有些場景下完全可以作為一個獨立的工具來使用的,這里模擬一個代碼檢測工具的應用,完全可以作為一個流程引擎來使用

const koaCompose = require('koa-compose');
function download = (ctx, next) {
  console.log('download code');
  next();
}
function check = (ctx, next) {
  console.log('check style');
  next();
}
function post = (ctx, next) {
  next();
  console.log('post result', ctx.result);
}
function clean = (ctx, next) {
  next();
  console.log('clean temp, remove code');
}
const flowEngine = koaCompose([download, check, post, clean]);
flowEngine(ctx as Context);

上述可以看作一個基于koa-compose實現(xiàn)的流程引擎,在node中,我們會經(jīng)常處理一些多階段的任務,完全可以通過這樣的方式來實現(xiàn)

總結(jié)

koa的洋蔥圈模型在面試中經(jīng)常會被問到,建議可以寫一下、理解一下koa-compose的源碼;另外koa-compose作為一個流程引擎也是一個很有用的工具,在有些場景下會有意想不到的效果。

以上就是20行代碼簡單實現(xiàn)koa洋蔥圈模型示例詳解的詳細內(nèi)容,更多關于koa洋蔥圈模型的資料請關注腳本之家其它相關文章!

相關文章

  • Node.js中下包速度慢問題解決方法分析

    Node.js中下包速度慢問題解決方法分析

    這篇文章主要介紹了Node.js中下包速度慢問題解決方法,分析了npm切換鏡像源以及nrm工具鏡像源管理相關使用技巧,需要的朋友可以參考下
    2023-04-04
  • Windows系統(tǒng)中安裝nodejs圖文教程

    Windows系統(tǒng)中安裝nodejs圖文教程

    這篇文章主要介紹了Windows系統(tǒng)中安裝nodejs圖文教程,本文分解了安裝中的各個步驟并給出圖文說明,需要的朋友可以參考下
    2015-02-02
  • node.js中的buffer.Buffer.isBuffer方法使用說明

    node.js中的buffer.Buffer.isBuffer方法使用說明

    這篇文章主要介紹了node.js中的buffer.Buffer.isBuffer方法使用說明,本文介紹了buffer.Buffer.isBuffer的方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Windows中安裝nvm進行Node版本控制與詳細使用教程

    Windows中安裝nvm進行Node版本控制與詳細使用教程

    nvm和npm都是node.js版本管理工具,但是為了解決node各種不同之間版本存在不兼容的問題,因此可以通過nvm安裝和切換不同版本的node,感興趣的可以了解一下
    2023-09-09
  • 詳解HTTPS 的原理和 NodeJS 的實現(xiàn)

    詳解HTTPS 的原理和 NodeJS 的實現(xiàn)

    這篇文章主要介紹了詳解HTTPS 的原理和 NodeJS 的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • nvm mac 環(huán)境搭建過程

    nvm mac 環(huán)境搭建過程

    這篇文章主要為大家介紹了nvm mac 環(huán)境搭建過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • 在node中如何調(diào)用python腳本

    在node中如何調(diào)用python腳本

    這篇文章主要介紹了在node中如何調(diào)用python腳本,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Node.js 獲取微信JS-SDK CONFIG的方法示例

    Node.js 獲取微信JS-SDK CONFIG的方法示例

    這篇文章主要介紹了Node.js 獲取微信JS-SDK CONFIG的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • express框架通過ejs模板渲染輸出頁面實例分析

    express框架通過ejs模板渲染輸出頁面實例分析

    這篇文章主要介紹了express框架通過ejs模板渲染輸出頁面的方法,結(jié)合實例形式分析了express框架使用ejs模版引擎渲染輸出的相關操作技巧與使用注意事項,需要的朋友可以參考下
    2023-05-05
  • 詳解Express筆記之動態(tài)渲染HTML(新手入坑)

    詳解Express筆記之動態(tài)渲染HTML(新手入坑)

    這篇文章主要介紹了詳解Express筆記之動態(tài)渲染HTML(新手入坑),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12

最新評論

大足县| 固原市| 青海省| 正阳县| 大化| 宁安市| 丰宁| 耿马| 湛江市| 山东省| 新昌县| 右玉县| 曲麻莱县| 沙田区| 宜宾县| 顺昌县| 邯郸市| 南陵县| 广汉市| 襄垣县| 佛山市| 溆浦县| 渭源县| 高要市| 安远县| 汤阴县| 澄江县| 新营市| 阆中市| 西林县| 伊通| 漾濞| 周口市| 阳江市| 彰武县| 赣州市| 都安| 舞钢市| 阳信县| 梅河口市| 昌江|