日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

koa2源码分析

發(fā)布時間:2025/5/22 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 koa2源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

引言

最近在寫koa2相關例子,順便看了下koa2的源碼,下面是一些個人理解。

koa1核心基于generator,但是嚴重依賴co的包裝。koa2完全不需要,基于async(其實質(zhì)是generator的語法糖調(diào)用包裝),在node v7 下可直接運行。
關于async和generator的語法,本文不做贅述。下面先創(chuàng)建一個koa實例,然后基于入口一步步分析。

//koa code const Koa=require('koa'); const app=new Koa();app.use(async function (ctx, next) {console.log('>> one');await next();console.log('<< one'); }); app.use(ctx => {ctx.body='hello world gcy'; }); app.listen('3000',function () {console.log('listening on port 3000'); });

說明 上面這段代碼似乎有些神秘,其實質(zhì)是下面http module的封裝調(diào)用。

// native code let http=require('http'); let server=http.createServer(function (req,res) {res.writeHead(200,{'Content-type':'text/plain'});res.write('hello world gcy');res.end(); }); //start service listen server.listen(8000,function () {console.log('listening on port 8000'); });

下面基于koa構(gòu)造函數(shù)入口做進一步分析。

constructor() {super();this.proxy = false;//創(chuàng)建一個空數(shù)組存放放middleware,洋蔥流程的真相,下面會分析法到this.middleware = [];//決定忽略的子域名數(shù)量,默認為2this.subdomainOffset = 2;//處理環(huán)境變量this.env = process.env.NODE_ENV || 'development';//實例上掛載context,request,responsethis.context = Object.create(context);this.request = Object.create(request);this.response = Object.create(response);}

說明 上面是構(gòu)造函數(shù)入口,啟動入口如下

//借用原生http.createServer,添加app.callback。listen() {debug('listen');const server = http.createServer(this.callback());return server.listen.apply(server, arguments);}

說明 通過上面兩個步驟一個完整的web服務器建立起來。對于監(jiān)聽接受到的請求解析處理,是通過callback函數(shù),調(diào)用一系列中間件來完成。
下面分析中間件執(zhí)行流程,我認為koa的主要內(nèi)涵也就在這,所以做一下重點來論述。
首先引入經(jīng)典中間件洋蔥圖,以便理解。

結(jié)合這幅圖再看下面的代碼

核心代碼application 126 行 const fn = compose(this.middleware);return function (context, next) {let index = -1return dispatch(0)function dispatch (i) {if (i <= index) return Promise.reject(new Error('next() called multiple times'))index = ilet fn = middleware[i]if (i === middleware.length) fn = next//立即返回處于resolve狀態(tài)promise實例,以便后續(xù)邏輯繼續(xù)執(zhí)行if (!fn) return Promise.resolve()try {// await next(); //當fn里面執(zhí)行這句話時,就會執(zhí)行dispatch(i+1),導致洋蔥執(zhí)行過程// 整個過程類似堆棧執(zhí)行釋放過程中的的遞歸調(diào)用,雖然有差異,可借用類比思考其執(zhí)行順序流程return Promise.resolve(fn(context, function next () {return dispatch(i + 1)}))} catch (err) {return Promise.reject(err)}}// 核心代碼application 136 行 return fn(ctx)[是一個立即狀態(tài)的promise].then(handleResponse).catch(onerror);} }

如果結(jié)合注釋看上述代碼過程中存在疑惑,可進一步參考下面的進行思考,反之忽略即可。

const Koa=require('koa'); const app=new Koa();app.use(async function (ctx, next) {console.log('>> one');await next();console.log('<< one'); }); app.use(async function (ctx, next) {console.log('>> two');ctx.body = 'two';await next();console.log('<< two'); }); app.use(async function (ctx, next) {console.log('>> three');await next();console.log('<< three'); }); //如果放到首部,不方便理解洋蔥執(zhí)行流程,因為沒有調(diào)用next函數(shù) app.use(ctx => {ctx.body='hello world gcy'; }); app.listen('3000',function () {console.log('listening on port 3000'); });

說明 koa基于中間價架構(gòu),核心簡潔,除此之外還有一些其它相對重要的方法。

application.js

  • use(fn) //組裝use的傳參
  • createContext(req, res) 創(chuàng)建初始化的上下文,將req和res掛載在context上
  • onerror(err) 錯誤處理,當設定this.slient為true,不會輸出信息,在emit觸發(fā)時執(zhí)行
  • respond(ctx) http response簡單封裝,信息返回

context.js

  • delegate(proto, 'request') //Request相關方法委托,從而讓context作為調(diào)用入口
  • onerror(err) //中間件執(zhí)行過程中異常處理邏輯

除此之外還有request和response的參數(shù)解析文件,因為邏輯簡單,不做敘述。
雖然核心文件不多,但是其也require了不少包,下面列舉幾個比較重的,以作為示例。

require

  • events application繼承自Emitter,從而可以實現(xiàn)事件的訂閱發(fā)布。
  • koa-compose 中間件的封裝,核心邏輯之一,上面已分析。
  • debug 錯誤信息格式封裝處理
  • statuses http狀態(tài)碼和和相應信息對應處理
  • koa-convert 把generator轉(zhuǎn)為promise
  • …… and so on

總結(jié)

寫這篇文章起因,是在寫case的過程中,同一解決方案下中間件選擇的糾結(jié)癥,尤其是在選擇render template過程中,為找其本質(zhì)間差異,探尋到此。
源碼分析基于koa(version 2.2.0),通讀源碼之后,可以較清晰的開發(fā)或者使用別人的中間件,
如果你有不同的理解,歡迎留言交流。

總結(jié)

以上是生活随笔為你收集整理的koa2源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。