前言
Express和Koa是目前最主流的基於node的web開發框架,他們的開發者是同一班人馬。貌似現在Koa更加流行,但是仍然有大量的專案在使用Express,所以我想通過這篇文章說說Express中介軟體的原理。
中介軟體的功能和分類
中介軟體的本質就是一個函式,在收到請求和返回相應的過程中做一些我們想做的事情。Express文件中對它的作用是這麼描述的:
執行任何程式碼。
修改請求和響應物件。
終結請求-響應迴圈。
呼叫堆疊中的下一個中介軟體。
分類
Express文件中把他們分為了五類,但是他們的原理相同,只是用法不同:
應用級中介軟體
路由級中介軟體
錯誤處理中介軟體
內建中介軟體
第三方中介軟體
中介軟體的原理
首先我們看看中介軟體的用法:
var express = require(`express`)
var app = express();
app.use(`/user`, function (req, res, next) {
//TODO
next();
});
app.listen(8080)
複製程式碼
接下來我們對比看一下下原始碼:
與中介軟體有關的有三部分:
- express.js繼承application.js並對外暴露介面
- application.js掛載了所有核心方法
- router資料夾處理路由邏輯
先看express.js的程式碼:
這部分程式碼中最重要的是紅色方框部分,mixin
是一個第三方庫。可以簡單理解為繼承(實際上它不是繼承而是混合)。
接下來我們看application.js:
我把檔案下載下來並且刪去了註釋,通過這張圖我們可以看出這個檔案的作用是掛載了所有的方法(包括use等關鍵api)。
這裡面比較重要的是use
方法,它的作用就是把我們用app.use
註冊的所有中介軟體和路由方法交給Router
類來處理。
那我們再看看router資料夾類的結構:
index.js是入口檔案,處理所有的路由;
layer.js中宣告瞭Layer
類,處理每一層路由中介軟體或者每一個子中介軟體;
router.js中宣告瞭Router
類,處理每一個子路由。
這裡面有一個子中介軟體的概念,對應Exprees文件中有這一句話:
另外,你還可以同時裝載一系列中介軟體函式,從而在一個掛載點上建立一個子中介軟體棧。
這句話的意思是說我們可以把程式碼寫成下面這種形式:
app.use(`/user1`, function fn1(req, res, next) {
// TODO
next();
}, function fn2(req, res, next) {
//TODO
next();
});
app.use(`/user2`, function fn3(req, res, next) {
// TODO
next();
}, function fn4(req, res, next) {
//TODO
next();
});
複製程式碼
上面的程式碼給user1和user2分別建立了一個子中介軟體棧。這種語法的實現就是靠Layer
類實現的。
畫一張圖來解釋上面的程式碼:
解釋一下上面的程式碼和圖:
我們寫了兩個路由/user1和/user2,每個路由給了兩個處理函式。對於這段程式碼,Express是這樣處理的:
- 在index.js檔案中,定義了一個
stack
陣列,接下來會建立兩個Layer
放到這個stack
中。 - route.js模組會給/user1再建立一個
stack
和fn1、fn2兩個Layer
。 - /user2同/user1
- 最後,Express會從上往下執行每個
Layer
裡的函式,對應到圖上就是從上至下、從左至右的依次執行,順序為fn1、fn2、fn3、fn4。
最後
以上就是Express中介軟體的簡單原理,白話較多,如果寫的不準確的地方,希望大家批評指正。