node.js connect模塊解析

搭建網站時使用的express,是基於connect模塊開發的。這篇博客是經過分析connect源碼來分析中間件隊列處理HTTP請求的過程。源碼參考地址:https://github.com/senchalabs/connect/blob/master/index.js。文中若有不正確敬請指出。node

在express中咱們使用中間件是相似這樣的(圖片來自http://www.infoq.com/cn/articles/nodejs-connect-module):git

 1. 入口文件connect.js一共作了一件事:github

export createServer函數。express

下圖只提取部分(我以爲比較有表明性比較關鍵)功能的代碼。json

 2. 因此執行connect() 也就是執行createServer(),具體作了以下事情:數組

1)返回一個函數app,入口參數爲req, res。app有不少屬性方法,好比app.use, app.handle, app.listen,也支持事件。app的函數體就是執行app.handle(req, res, next)。閉包

2)爲app添加了stack屬性,用來保存中間件。初始值爲空數組。app

 

3. 當執行app.use(require('body-parser').json())的時候執行了什麼函數

1) 首先require('body-parser').json()返回一個函數parser,入口參數爲req, res, next。函數執行到最後會調用next();網站

2) app.use是將{route: '/', handle: parser}加入stack.

一樣的道理,app.use的過程是將中間件加入app.stack的過程。server啓動前stack中已經有一系列中間件。

 

4. app.listen(3000)

建立server實例:http.createServer(app)。因此app是收到HTTP請求後的回調。

 

5. 當一個HTTP請求到來後,因爲回調函數是app, 因此執行app.handle(req, res, next)。此時next是undefined。handle作了如下幾件事

1)req.originalUrl = req.originalUrl || req.url。保存初始url

2)var done = next || finalHandler(req, res, {env: env, onerror: logerror})

3)定義next函數並執行。next函數作了如下幾件事:

a. 獲取下一個中間件。index初始爲0

b. 若是layer爲undefined, 在下一個事件循環執行done.

c. 取出layer中route, 若是跟當前url不匹配,執行next(), 也就是執行下一個中間件。若是匹配,執行call(layer.handle, route, err, req, res, next)

 

6. call函數作的事情是:

1)執行handle。若是沒有錯誤,直接返回。handle函數中可能還會調用next, 好比bodyParser.json。若是有錯誤拋出,設置error。

2)若是出現了錯誤,執行next(error);

7. 中間件隊列遍歷結束,執行finalHandler。若是某個中間件直接執行res.send之類的操做,再也不執行next, 請求處理結束。

 

因此請求從發送到返回的過程就是req被若干個中間件函數處理,每一個函數對req有一點修改,而後傳遞給下一個中間件函數。next函數是一個閉包,而且一直做爲參數被傳遞,index共享。

相關文章
相關標籤/搜索