参考视频: Node for Beginners 之 connect
来,分析源码前,我们先看看几个概念!
首先, 一个http请求从客户端传到了服务器,接下来要怎么样?当然是处理这个请求啊喂!如果不用connect模块,直接用一个简单粗暴的回调函数: http.createServer(func).listen(8888);console.log('Server is running...');
服务器受到来自客户端的请求,然后执行func(req, res) {...}
这样一个回调函数。
咦,好像是OK的呢。然而,有个简单粗暴的问题: 如果这个回调函数异常复杂呢,逻辑很长,重点是它内部也有很多一系列串联的事情要执行呢?这时候你还笼统的刀耕火种自己写,就out啦,这就是为什么我们要组件化,模块化嘛——也就是connect存在的意义啦!
再来,看一下什么是中间件:我们把早上起床从家去到公司这件事当成一个任务,你要先出家的大门,然后出小区的大门,再然后走大道过马路,到达公司的写字楼大厅,然后再到达你公司的具体门牌号。看到了没有,你从家去公司是可以拆分为这样一个由5个小过程组成的一件事,那么就有 a,b,c,d,e这5个中间件,以a为例,它包含三个要素,一是我的起点在哪(床上),二是我的终点在哪(家的大门),三是我的下一部是谁(b中间件), 类似,其他中间件也如此。a的具体内部实现,就是定义实现怎样从床上到出家的大门的过程。
最后,我们要理清楚,到底什么叫做“服务器接收到了客户端的请求后处理请求”。这个概念很重要,很有可能这个细节的理解有小问题,会导致对整个connect模块的理解都很疑惑。打个比方,你去餐厅对服务员说,给我来一桶油漆两个刷子。现实中的服务员会告诉你我们是餐厅不是五金店,他收到了请求,但是不会有反应。对应的node世界里面的服务员(服务器)没感觉,不会理你的。你只有点餐,点他们店里有的东西,他才有反应啊喂!也就是说,服务器提供了一系列你可以访问的东西,也定义了一系列它会做处理会响应的请求,如果服务器就只对index.html和about.html这两个请求定义了响应,你如果请求hello.html,服务器是会处理你的请求的,但是处理的结果就是没反应,因为服务器根本没准备要对任何其他的请求做出反应。所以,“服务器接收到了客户端的请求后处理请求”的概念是说,服务器接收到了你正确 的请求,即,不仅接收到了,且内部有对此请求的响应的定义。
来,现在把引入connect模块,让程序run起来先!
var connect = require('connect');
var http = require('http');
var app = connect();
function doFirst(request, response, next) {
console.log("bacon");
next();
}
function doSecond(request, response, next) {
console.log("tuna");
next();
}
app.use(doFirst);
app.use(doSecond);
http.createServer(app).listen(8888);
console.log('Server is running...');
- 首先引入依赖的模块,
var app = connect();
app内部自身有use方法和handle方法。 - 使用
app.use
,将两个中间件函数注册到app的内部队列stack数组里。简单说,就是找个地方依次放好中间件函数。 - 使用
http.createServer(app).listen(8888);
创建服务器并监听8888端口。现在只是有服务器run起来了,但是客户端还没发起链接动作呢。所以只是打印了'server is running'这句话。并没有打印别的。 - 来,现在快来浏览器地址栏敲下
localhost:8888
,大力按下回车键~啪!好,客户端请求发给服务器了。 - 现在服务器也收到请求了,开始响应,也就是运行这里的app函数。
- app调用内部的handle()方法,handle干了什么事情呢:次执行之前用app.use注册到Stack数组里的一系列的中间件函数。
最开始的初衷是贴上connect.js的源码,分析内部实现的,实在太长而且琐碎,取其琐碎取其精华,抽取出主要部分,也就浓缩成以上的过程了。其中中间还有个比较重要的内容就是stack数组里面一条一条的到底是什么,里面还涉及到route和path,以后有心情的时候我再补写吧。