Express中間件原理詳解

前言

      Express和Koa是目前最主流的基於node的web開發框架,他們的開發者是同一班人馬。貌似如今Koa更加流行,可是仍然有大量的項目在使用Express,因此我想經過這篇文章說說Express中間件的原理。html

中間件的功能和分類

      中間件的本質就是一個函數,在收到請求和返回相應的過程當中作一些咱們想作的事情。Express文檔中對它的做用是這麼描述的:node

執行任何代碼。
修改請求和響應對象。
終結請求-響應循環。
調用堆棧中的下一個中間件。
git

分類

      Express文檔中把他們分爲了五類,可是他們的原理相同,只是用法不一樣:github

應用級中間件
路由級中間件
錯誤處理中間件
內置中間件
第三方中間件
web

中間件的原理

      首先咱們看看中間件的用法:express

var express = require('express')
var app = express();
app.use('/user', function (req, res, next) {
  //TODO
  next();
});
app.listen(8080)

複製代碼

      接下來咱們對比看一下下源碼:api

      與中間件有關的有三部分:

  • express.js繼承application.js並對外暴露接口
  • application.js掛載了全部核心方法
  • router文件夾處理路由邏輯

      先看express.js的代碼:數組

      這部分代碼中最重要的是紅色方框部分,mixin是一個第三方庫。能夠簡單理解爲繼承(實際上它不是繼承而是混合)。
bash

      接下來咱們看application.js:app

      我把文件下載下來而且刪去了註釋,經過這張圖咱們能夠看出這個文件的做用是掛載了全部的方法(包括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是這樣處理的:

  1. 在index.js文件中,定義了一個stack數組,接下來會建立兩個Layer放到這個stack中。
  2. route.js模塊會給/user1再建立一個stack和fn一、fn2兩個Layer
  3. /user2同/user1
  4. 最後,Express會從上往下執行每一個Layer裏的函數,對應到圖上就是從上至下、從左至右的依次執行,順序爲fn一、fn二、fn三、fn4。

最後

      以上就是Express中間件的簡單原理,白話較多,若是寫的不許確的地方,但願你們批評指正。

參考資料

Express官網
Express的github倉庫地址

相關文章
相關標籤/搜索