摘要:是一個非常輕量的框架,里面除了和之外什么都沒有,甚至連最基本的功能都需要通過安裝其他中間件來實現。而的源碼同樣很簡潔,基礎代碼只有不到行,非常適合閱讀學習。的源碼直接從獲取,本文采用目前最新的版本。
koa是一個非常輕量的web框架,里面除了ctx和middleware之外什么都沒有,甚至連最基本的router功能都需要通過安裝其他中間件來實現。不過雖然簡單,但是它卻非常強大,僅僅依靠中間件機制就可以構建完整的web服務。而koa的源碼同樣很簡潔,基礎代碼只有不到2000行,非常適合閱讀學習。
koa的源碼直接從github獲取,本文采用目前最新的2.5.1版本。
代碼結構第一眼看到koa的源碼時候我真的懵了,反復確認沒有看錯之后才確信,koa源碼只有四個文件--application.js,context.js,request.js,response.js,位于項目的lib文件夾下。而且一看文件名基本上就能猜到每個文件是做什么的了,接下來就是打開查看里面的內容。
koa基本啟動流程首先看package.json里面的main,可以知道application.js是入口文件,里面是一個繼承自event模塊下的Emitter類的Application類,我們使用koa時候創建的app實例就是在這里定義的。
分析一個類自然要先看它的構造函數,里面重點的就是定義了一個數組middleware,還有三個屬性context,request,response分別為三個對象,而這三個對象就是在對應的其他三個文件中定義的。在此我們先不看另外的文件,想想我們使用koa的時候,創建app實例之后,接下來就是use各種中間件了,所以直接看use方法。
use接收一個中間件函數作為參數,首先做類型校驗,如果傳入的是generator,在koa2中會先通過convert進行轉換(此處是為了兼容koa1,后續版本將移除),最后其實只做了一件事,就是把這個函數push到middleware數組中去。use方法最后會返回this,也就是koa實例本身,這就意味著我們可以實現鏈式調用。
設置好中間件,我們開啟koa服務的最后一步就是調用listen方法設置監聽端口,接下來就看一下listen方法的實現。我們會發現listen更簡單,只有兩行,其實什么額外的事情也沒做,只是調用了node原生的http模塊下面的createServer方法創建服務,listen方法設置監聽,僅此而已。我們都知道http的createServer需要傳入一個函數,這個函數在koa里面是通過調用callback方法返回的,接下來看callback的實現。
callback里面首先使用compose把所有的中間件變成一個函數(compose的實現同樣后續會詳細分析),這里會首先調用Emitter中的listenerCount方法判斷是否有error事件的監聽器,如果沒有會為error事件注冊默認的事件監聽方法onerror,之后就是定義我們要的那個傳入createServer的函數了。這個函數接收req和res兩個參數,之后,koa會對其做一個處理:通過調用createContext方法把req和res封裝成我們熟悉的ctx對象(createContext具體做了哪些工作接下來會說),然后把ctx和之前處理好的中間件函數fnMiddleware傳入handleRequest方法中。
handleRequest中首先先取出res,先把狀態置為404,然后對執行中間件后的成功和失敗狀態注冊方法,失敗調用ctx.onerror捕獲異常,成功調用respond方法處理結果。這里還是用了onFinished模塊,onFinished能確保一個流在關閉、完成和報錯時都會執行相應的回調函數,這里把我們的異常處理函數傳入用以處理錯誤信息。而respond方法,里面做的,就是讀取ctx信息,把數據寫入res中并響應請求。至此,整個流程就完成了。
ctx的創建createContext里面的代碼其實特別簡單,就是創建了三個對象context,request,response,然后把使用ctx時候的各種東西都掛到context對象上,這樣我們就可以在ctx上面獲取到req,res等等各種信息了。創建context,request,response對象時候用到了當前app類里面的三個對象,它們是通過從外部三個文件中引入的對象來創建的,所以接下來就看一下這三個文件中都有什么。
這三個文件導出的都是對象,在context中,只做了一些基礎方法的定義,剩下的一切屬性方法全部都使用delegate代理到request和response屬性的訪問了。而前面我們已經知道,context上面的request和response就是通過另外的兩個文件中的對象創建得到的。而這兩個文件的內容就更加簡潔了,都是我們平時使用時候訪問的屬性和方法,通過getter和setter的方式來控制上面的req和res從而實現對實際請求和響應操作的封裝。于是整個koa核心的四個文件就徹底完成了。
compose實現原理與中間件機制首先做一些合法性校驗,重點在于最后的返回結果是一個函數,這個函數就是我們上面的fnMiddleware,它同樣也有context和next兩個參數,在其內部采用index變量記錄當前處理到哪個中間件,然后從第一個開始調用dispatch方法。首先會判斷當前傳入參數與index的關系,如果在一個中間件內多次調用next,會出現參數小于index的情況,此時就會報錯。之后把當前中間件從數組中取出來,每次執行時會把ctx和next傳入,next中調用dispatch,參數為下一個位置,這樣就會按順序把中間件添加進來,最后當i等于中間件數組長度時候,也就是沒有其他中間件了,那么執行一開始傳入的next參數,如果fn不存在,返回空的promise。當中心執行完,也就是前一個中間件的next執行完,自然會觸發await向下執行,之后執行權會反向順序返回,最終組合的結果就是先從外向里,再從里向外,就是我們熟知的洋蔥圈模型。
錯誤處理機制koa的錯誤處理機制也很有特點,我們只要監聽koa實例的error事件,就可以統一處理所有的錯誤。我們在前面提到過,調用fnMiddleware失敗后會被統一的onerror方法捕獲,這個方法是對應到ctx上的onerror方法,我們來看一下里面的實現,里面非常重要的一行就是this.app.emit("error", err, this);,由于我們的koa是繼承自event,所以可以派發出一個error事件,我們只要處理該事件即可。而前面在中間件處理中,如果發生錯誤就會reject,自然可以被catch捕獲到。
以上,就是koa基本核心模塊的流程,原理很簡單,但是配合各種中間件,koa完全可以實現一個功能完整web server。
本文原創,愿意分享但轉載請提前告知,更多文章查看我的主頁,感謝閱讀,如錯誤歡迎指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94819.html
摘要:引言最近空閑時間讀了一下的源碼在閱讀的源碼的過程中,我的感受是代碼簡潔思路清晰不得不佩服大神的水平。調用的時候就跟有區別使用必須使用來調用除了上面的的構造函數外,還暴露了一些公用的,比如兩個常見的,一個是,一個是。 引言 最近空閑時間讀了一下Koa2的源碼;在閱讀Koa2(version 2.2.0)的源碼的過程中,我的感受是代碼簡潔、思路清晰(不得不佩服大神的水平)。下面是我讀完之后...
摘要:實現的四大模塊上文簡述了源碼的大體框架結構,接下來我們來實現一個的框架,筆者認為理解和實現一個框架需要實現四個大模塊,分別是封裝創建類構造函數構造對象中間件機制和剝洋蔥模型的實現錯誤捕獲和錯誤處理下面我們就逐一分析和實現。 什么是koa框架? ? ? ? ?koa是一個基于node實現的一個新的web框架,它是由express框架的原班人馬打造的。它的特點是優雅、簡潔、表達力強、自由度...
摘要:實現的四大模塊上文簡述了源碼的大體框架結構,接下來我們來實現一個的框架,筆者認為理解和實現一個框架需要實現四個大模塊,分別是封裝創建類構造函數構造對象中間件機制和剝洋蔥模型的實現錯誤捕獲和錯誤處理下面我們就逐一分析和實現。 什么是koa框架? ? ? ? ?koa是一個基于node實現的一個新的web框架,它是由express框架的原班人馬打造的。它的特點是優雅、簡潔、表達力強、自由度...
閱讀 2144·2023-04-26 00:38
閱讀 1930·2021-09-07 10:17
閱讀 887·2021-09-02 15:41
閱讀 637·2021-08-30 09:45
閱讀 541·2019-08-29 17:25
閱讀 3204·2019-08-29 15:07
閱讀 2182·2019-08-29 12:52
閱讀 3734·2019-08-26 13:35