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共享。

相关文章
相关标签/搜索