1.3.2 最早的Connect

在1.3.1节的例子中,如果URL有成百上千个,甚至更多,该怎么办呢?用if/else写起来是不是太低效了?这种情况下肯定要进行封装,让代码更简单。任何重复的工作都应该被抽象,Connect就是这样抽象出来的框架。下面让我们来看一下关于Connect的介绍。

Connect是一个用Node.js编写的可扩展的HTTP服务器端框架,因以中间件作为“插件”而广为人知。

Connect的入门示例都很简单,如下。

回想一下1.3.1节中的http模块的例子,将

进行对比,可以看出如下几点。

○ 它们都是基于http.createServer的。

○ 它们的差异是,createServer的参数是独立的,并且在Connect里通过app.use函数可以挂载多个插件式的中间件。

○ Connect中提供了一个独立的app层。

○ Connect支持中间件写法,可以通过app.use函数挂载中间件。

编程时会区分可变状态和不可变状态,可变的抽取出去,不可变的固化下来。Connect提供了可变部分的插件化,对于Node.js Web应用开发来说,这是演进中必要的一步。

➘ 多URL处理

我们来看一下Connnet如何处理多个URL,示例代码如下。

访问http://127.0.0.1:3011/2查看能否返回“Hello from Connect2!”字符串,如果可以,说明请求经过了第一个中间件。

前面介绍过,Connect实际上是将开发中的可变部分抽象出来,通过app.use函数挂载到app对象上的。这样处理起来非常简单、清晰。

➘ 中间件执行顺序

下面我们来看一下中间件执行顺序,connect2.js的内容如下。

访问http://127.0.0.1:3011/2查看能否连接,答案是不能,原因是第一个use方法里没有指定路径,而这时候它响应了所有的请求,这样第二个use方法的中间件就不会收到任何请求,所以正确的写法应该如下。

这其实和1.3.1节原始http模块里编写的if判断一样。

这样的写法是不是很讨厌?必须考虑中间件执行顺序让很多人埋怨Node.js中的“坑”太多。但这是真的有问题,还是自己没有弄明白,很值得反思。

通过前面的代码对比,我们能得出如下的结论。

○ app.use的中间件有顺序。

○ 中间件可分类:全局的和局部的(路由里生效的)。

○ 中间件的定义方法是function(req,res){}。

➘ 启动服务

Connect模块本质上只是对http模块的封装,提供了更统一的中间件形式,这对解耦抽象是非常重要的。但无论如何,Connect的最终返回结果是http.createServer参数中的回调函数,故而启动过程和普通的HTTP服务器的启动过程是一样的。