Express中間件的原理及實現(xiàn)

參考文章:初學nodejs一:別被Express的API搞暈了

GitHub,歡迎star:https://github.com/BadWaka/node-express-middleware-study

在Node開發(fā)中免不了要使用框架,比如express、koakoa2

拿使用的最多的express來舉例子

開發(fā)中肯定會用到很多類似于下面的這種代碼

var express = require('express');
var app = express();
app.listen(3000, function () {
    console.log('listen 3000...');
});

app.use(middlewareA);
app.use(middlewareB);
app.use(middlewareC);

對我要說的就是app.use()

為什么要說這個?因為面試時被問到了。。。

哦 你用過Express啊 來來來 那你說說app.use的原理是什么?

一臉懵逼...0.0

app.use()就是通常所說的使用中間件

那中間件是什么呢?它又有啥用呢?

中間件 middleware

一個請求發(fā)送到服務器后,它的生命周期是 先收到request(請求),然后服務端處理,處理完了以后發(fā)送response(響應)回去

而這個服務端處理的過程就有文章可做了,想象一下當業(yè)務邏輯復雜的時候,為了明確和便于維護,需要把處理的事情分一下,分配成幾個部分來做,而每個部分就是一個中間件

node.js - express 框架中的app.use是什么作用? - SegmentFault

app.use 加載用于處理http請求的middleware(中間件),當一個請求來的時候,會依次被這些 middlewares處理。

中間件執(zhí)行的順序是你定義的順序

那中間件到底是個什么東西呢?

中間件其是一個函數(shù),在響應發(fā)送之前對請求進行一些操作

function middleware(req,res,next){
    // 做該干的事

    // 做完后調用下一個函數(shù)
    next();
}

這個函數(shù)有些不太一樣,它還有一個next參數(shù),而這個next也是一個函數(shù),它表示函數(shù)數(shù)組中的下一個函數(shù)

那函數(shù)數(shù)組又是什么呢

express內部維護一個函數(shù)數(shù)組,這個函數(shù)數(shù)組表示在發(fā)出響應之前要執(zhí)行的所有函數(shù),也就是中間件數(shù)組

使用app.use(fn)后,傳進來的fn就會被扔到這個數(shù)組里,執(zhí)行完畢后調用next()方法執(zhí)行函數(shù)數(shù)組里的下一個函數(shù),如果沒有調用next()的話,就不會調用下一個函數(shù)了,也就是說調用就會被終止

Express中間件的使用

理論部分簡單的說了一下,現(xiàn)在來用代碼驗證一下,注意需要安裝一下express

/**
 * express中間件的實現(xiàn)和執(zhí)行順序
 *
 * Created by BadWaka on 2017/3/6.
 */
var express = require('express');

var app = express();
app.listen(3000, function () {
    console.log('listen 3000...');
});

function middlewareA(req, res, next) {
    console.log('middlewareA before next()');
    next();
    console.log('middlewareA after next()');
}

function middlewareB(req, res, next) {
    console.log('middlewareB before next()');
    next();
    console.log('middlewareB after next()');
}

function middlewareC(req, res, next) {
    console.log('middlewareC before next()');
    next();
    console.log('middlewareC after next()');
}

app.use(middlewareA);
app.use(middlewareB);
app.use(middlewareC);

輸出結果:


可以看到在執(zhí)行完下一個函數(shù)后又會回到之前的函數(shù)執(zhí)行next()之后的部分
這可以理解為中間件的一個特性吧

現(xiàn)在可以說已經明白Express的中間件是什么了,以及app.use的用法了,下面就來自己實現(xiàn)一下吧

實現(xiàn)簡單的Express中間件

/**
 * 仿照express實現(xiàn)中間件的功能
 *
 * Created by BadWaka on 2017/3/6.
 */

var http = require('http');

/**
 * 仿express實現(xiàn)中間件機制
 *
 * @return {app}
 */
function express() {

    var funcs = []; // 待執(zhí)行的函數(shù)數(shù)組

    var app = function (req, res) {
        var i = 0;

        function next() {
            var task = funcs[i++];  // 取出函數(shù)數(shù)組里的下一個函數(shù)
            if (!task) {    // 如果函數(shù)不存在,return
                return;
            }
            task(req, res, next);   // 否則,執(zhí)行下一個函數(shù)
        }

        next();
    }

    /**
     * use方法就是把函數(shù)添加到函數(shù)數(shù)組中
     * @param task
     */
    app.use = function (task) {
        funcs.push(task);
    }

    return app;    // 返回實例
}

// 下面是測試case

var app = express();
http.createServer(app).listen('3000', function () {
    console.log('listening 3000....');
});

function middlewareA(req, res, next) {
    console.log('middlewareA before next()');
    next();
    console.log('middlewareA after next()');
}

function middlewareB(req, res, next) {
    console.log('middlewareB before next()');
    next();
    console.log('middlewareB after next()');
}

function middlewareC(req, res, next) {
    console.log('middlewareC before next()');
    next();
    console.log('middlewareC after next()');
}

app.use(middlewareA);
app.use(middlewareB);
app.use(middlewareC);

JS是一門神奇的語言,這里用到了兩個閉包,并且給app這個函數(shù)添加了一個use方法,函數(shù)也是可以有屬性的

原理就是每調用一次use,就把傳進來的函數(shù)扔到express內部維護的一個函數(shù)數(shù)組中去

測試結果:


ok,相信對Express中間件的原理已經有所了解了,koa和koa2中間件的原理其實也是一樣的

繼續(xù)去看源碼了。。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容