node.js-express的app.use()初步理解


先看最簡單的node的hello world

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337);

上面這段就是來一個請求,就用傳給createServer的匿名函數來處理請求。

 

使用Express的代碼

var app = express();
//...中間忽略
http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

對比可以看出,執行express()后,會返回一個函數,賦值給app,app的簽名應該為:

function(req,res){//...}

然后請求都會被app這個函數處理(因為這個app是執行express后的結果,下面將不加區分的使用app和express兩個詞)。

 

可以認為,在express內部,有一個函數的數組,暫時叫這個數組tasks,每來一個請求express內部會依次執行這個數組中的函數(這里說依次並不嚴謹,每個函數必須滿足一定條件才行,這個后面說),應該可以想到,在這個函數數組里,每個函數的簽名應該像下面那樣:

function(req,res){//...}

但是,實際上是:

function(req,res,next){//...}

這個next,是指下一個函數。后面我們會寫一些試驗來體驗一下這個next,先總結一下:

對於一個典型的使用express的app.js,做了以下幾件事

  • 1.導入相關模塊
  • 2.執行過 var app = express() 后,
    • 使用app.set 設置express內部的一些參數(options)
    • 使用app.use 來注冊函數,可以簡單的認為是向那個(被我叫做)tasks的數組進行push操作
  • 3.通過http.createServer 用app來處理請求

試驗一: 向express中注冊自定義函數

注冊進express中的函數,需要滿足(請見下面更正)

1.長成下面這個樣子:

function(req,res,next){
    //...我們自己的邏輯
    next();
}

2.app.use(customerFunc) 要寫在下面兩句的前面:

app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

關於第2點,是因為路由后或請求靜態資源后,一次請求響應的生命周期實質上已經結束,加在這后面進行請求處理,沒有任何意義。

關於第1點,寫點代碼就好了:

app.use(function(req,res,next){
    console.log("111");
    next();
});

如果不寫next(),那么后面注冊的函數就不會執行,運行試一下就知道了。

再來一個:

app.use(function(req,res,next){
    console.log('111');
    next();
    console.log('222');
});

app.use(function(req,res,next){
    console.log("333");
    next();
});

那么控制台的輸出的順序是:111 333 222

更正:

上面說,自定義的函數應該滿足兩個條件,一般使用是那樣。但是,也可以兩個都不滿足。。。比如,自定義函數可以是4參數的,放在最后做通用error處理。:

app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

在上面兩句之后可以加一個:

app.use(function(err,req,res,next){
    if(err){
         //自己的處理錯誤的邏輯
         console.log(err.message);
         console.log(err.stack);
         res.end('404')  
    }
});

 

試驗二: next()的工作原理

在理解的上面的過程后,能不能不借助express,自己實現上面的過程呢,主要是怎么處理next()那一塊:

function express(){
    var funcs = [];

    var expr = function(req,res){
        var i = 0;
        function next(){            
            var task = funcs[i++];
            if(!task) return;
            task(req,res,next);
        }
        next();
    }
    expr.use=function(f){
        funcs.push(f);
    }
    return expr;
}
var app = express();

app.use(function(req,res,next){
    console.log('haha');
    next();
});
app.use(function(req,res,next){
    console.log('hehe');
    next();
});
app.use(function(req,res){
    res.end("there is nothing happened");
});

http.createServer(app).listen('3000', function(){
  console.log('Express server listening on port 3000');
});

啟動服務后,每來一個請求,控制台會依次輸出haha hehe,然后瀏覽器是there is nothing happened

當然如果要更深一步,可以去看原代碼,實際上這一部分的主要代碼是在connect中的,在connect/lib/proto.js 這個源文件中,主要是app.use,和app.handle 兩個函數中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM