摘要:下面基于構造函數入口做進一步分析。創建一個空數組存放放,洋蔥流程的真相下面會分析法到決定忽略的子域名數量,默認為處理環境變量實例上掛載說明上面是構造函數入口啟動入口如下借用原生,添加。
引言
最近在寫koa2相關例子,順便看了下koa2的源碼,下面是一些個人理解。
koa1核心基于generator,但是嚴重依賴co的包裝。koa2完全不需要,基于async(其實質是generator的語法糖調用包裝),在node v7 下可直接運行。
關于async和generator的語法,本文不做贅述。下面先創建一個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"); });
說明 上面這段代碼似乎有些神秘,其實質是下面http module的封裝調用。
// 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構造函數入口做進一步分析。
constructor() { super(); this.proxy = false; //創建一個空數組存放放middleware,洋蔥流程的真相,下面會分析法到 this.middleware = []; //決定忽略的子域名數量,默認為2 this.subdomainOffset = 2; //處理環境變量 this.env = process.env.NODE_ENV || "development"; //實例上掛載context,request,response this.context = Object.create(context); this.request = Object.create(request); this.response = Object.create(response); }
說明 上面是構造函數入口,啟動入口如下
//借用原生http.createServer,添加app.callback。 listen() { debug("listen"); const server = http.createServer(this.callback()); return server.listen.apply(server, arguments); }
說明 通過上面兩個步驟一個完整的web服務器建立起來。對于監聽接受到的請求解析處理,是通過callback函數,調用一系列中間件來完成。
下面分析中間件執行流程,我認為koa的主要內涵也就在這,所以做一下重點來論述。
首先引入經典中間件洋蔥圖,以便理解。
結合這幅圖再看下面的代碼
////核心代碼application 126 行 const fn = compose(this.middleware); return function (context, next) { let index = -1 return dispatch(0) function dispatch (i) { if (i <= index) return Promise.reject(new Error("next() called multiple times")) index = i let fn = middleware[i] if (i === middleware.length) fn = next //立即返回處于resolve狀態promise實例,以便后續邏輯繼續執行 if (!fn) return Promise.resolve() try { // await next(); //當fn里面執行這句話時,就會執行dispatch(i+1),導致洋蔥執行過程 // 整個過程類似堆棧執行釋放過程中的的遞歸調用,雖然有差異,可借用類比思考其執行順序流程 return Promise.resolve(fn(context, function next () { return dispatch(i + 1) })) } catch (err) { return Promise.reject(err) } } // 核心代碼application 136 行 return fn(ctx)[是一個立即狀態的promise].then(handleResponse).catch(onerror); } }
如果結合注釋看上述代碼過程中存在疑惑,可進一步參考下面的進行思考,反之忽略即可。
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"); }); //如果放到首部,不方便理解洋蔥執行流程,因為沒有調用next函數 app.use(ctx => { ctx.body="hello world gcy"; }); app.listen("3000",function () { console.log("listening on port 3000"); });
說明 koa基于中間價架構,核心簡潔,除此之外還有一些其它相對重要的方法。
application.jsuse(fn) //組裝use的傳參
createContext(req, res) 創建初始化的上下文,將req和res掛載在context上
onerror(err) 錯誤處理,當設定this.slient為true,不會輸出信息,在emit觸發時執行
respond(ctx) http response簡單封裝,信息返回
context.jsdelegate(proto, "request") //Request相關方法委托,從而讓context作為調用入口
onerror(err) //中間件執行過程中異常處理邏輯
除此之外還有request和response的參數解析文件,因為邏輯簡單,不做敘述。
雖然核心文件不多,但是其也require了不少包,下面列舉幾個比較重的,以作為示例。
events application繼承自Emitter,從而可以實現事件的訂閱發布。
koa-compose 中間件的封裝,核心邏輯之一,上面已分析。
debug 錯誤信息格式封裝處理
statuses http狀態碼和和相應信息對應處理
koa-convert 把generator轉為promise
…… and so on
總結寫這篇文章起因,是在寫case的過程中,同一解決方案下中間件選擇的糾結癥,尤其是在選擇render template過程中,為找其本質間差異,探尋到此。
源碼分析基于koa(version 2.2.0),通讀源碼之后,可以較清晰的開發或者使用別人的中間件,
如果你有不同的理解,歡迎留言交流。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82202.html
摘要:洋蔥圈處理模型。基于的靈活強大的中間件機制。參考官網提供的基本,不在贅述部分實現,參考源碼分析常用服務端口監聽返回適用于方法的回調函數來處理請求。 本文 github 地址: https://github.com/HCThink/h-blog/blob/master/source/koa2/readme.md github 首頁(star+watch,一手動態直達): https:...
摘要:本筆記共四篇源碼閱讀筆記源碼閱讀筆記源碼閱讀筆記服務器啟動與請求處理源碼閱讀筆記對象起因前兩天終于把自己一直想讀的源代碼讀了一遍。首先放上關鍵的源代碼在上一篇源碼閱讀筆記服務器啟動與請求處理中,我們已經分析了的作用。 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4...
摘要:如果驗證沒出現問題,就注冊這個中間件并放到中間件數組中。但如果不執行,中間件的處理也會終止。整理下流程默認會執行中間件數組中的第一個,也就是代碼中的,第一個中間件通過返回的是第二個中間件的執行。 介紹 如果你使用過redux或者nodejs,那么你對中間件這個詞一定不會感到陌生,如果沒用過這些也沒關系,也可以通過這個來了解javascript中的事件流程。 一個例子 有一類人,非常的懶...
摘要:頁面預覽頁面主要分為話題列表頁消息頁面個人信息頁面創建話題頁面個人設置頁面注冊頁面登陸頁面頁面。還有權限方面的,比如登陸后不可以再進入登陸頁面,未登陸也不可以進入創建主題頁面。沒有使用,但推介使用,不然性能不好。 技術棧 線上地址:點擊查看 (訪問會有點慢,至于原因,下面會說明)前端(主要):reactv15.6.1、react routerv4.2.0、reduxv3.7.2、ant...
摘要:實現的四大模塊上文簡述了源碼的大體框架結構,接下來我們來實現一個的框架,筆者認為理解和實現一個框架需要實現四個大模塊,分別是封裝創建類構造函數構造對象中間件機制和剝洋蔥模型的實現錯誤捕獲和錯誤處理下面我們就逐一分析和實現。 什么是koa框架? ? ? ? ?koa是一個基于node實現的一個新的web框架,它是由express框架的原班人馬打造的。它的特點是優雅、簡潔、表達力強、自由度...
閱讀 1985·2021-09-26 10:19
閱讀 3257·2021-09-24 10:25
閱讀 1641·2019-12-27 11:39
閱讀 1929·2019-08-30 15:43
閱讀 670·2019-08-29 16:08
閱讀 3509·2019-08-29 16:07
閱讀 909·2019-08-26 11:30
閱讀 1273·2019-08-26 10:41