一,开篇分析

大家好,今天这篇文章主要是对"Connect"中间件以及相关辅助中间件,做一个源码分析系列,我想上一篇文章大家也看了,

介绍了使用方式及用途,而这篇也是出于本人的兴趣,让读者对其有一个更深入的认识,如在分析阶段有什么不正确的地方,请大家多多指教,

好了!老规矩然我们进入正题。先来看一个例子,结合会用引入分析,如下:

复制代码代码如下:
 var connect = require("./lib/connect") ;
 var app = connect.createServer() ;
 app.use(connect.static(__dirname + "/public",{
    maxAge: 0 
})) ;
 app.use(function(req,res,next){
     res.end("Hello World !") ;
 })
 .listen(8888) ;

 

  二,逐行分析:

  (1),第一行,引入"connect"模块,通过connect创建一个http|https server,提供http server的所有功能。

    "connect"中间件允许你用多种方式创建"server",   

复制代码代码如下:
var server = connect.createServer(
     connect.logger()
    , connect.static(__dirname + '/public')
) ; // 1
var app = connect() ;
app.use(function (req,res) {
    res.end("Hello,大雄君 !\n")  ;
}).listen(8888)  ; // 2

  那么它是如何做的那,看源码:

复制代码代码如下:
exports = module.exports = createServer ;
exports.createServer = createServer ;

  将“createServer”挂载到全局的“exports”上,然后再扩展一个“createServer”属性再次挂载,目的是为了兼容原生的书写形式,

达到了不同方式创建的目的。这也是大家在平时开发中可以借鉴的思想。

  (2),再来看第二行"connect.createServer",做了什么那,看如下源码:

复制代码代码如下:
 var HTTPServer = require('./http').Server , 
 HTTPSServer = require('./https').Server ;
 function createServer() {
   if ('object' == typeof arguments[0]) {
     return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1));
   } else {
     return new HTTPServer(Array.prototype.slice.call(arguments));
   }
 };

  "HTTPSServer"和"HTTPServer"基本一致,只是"HTTPSServer"封装的https的方法。在"createServer"的时候,同样可以传递进去一系列的中间件,和随后引入的效果是一样的,不过却只能绑定到根目录上。

  (3),继续看第三行"app.use()",做了什么那,看如下源码:  

复制代码代码如下:
 var Server = exports.Server = function HTTPServer(middleware) {
   this.stack = [];
   middleware.forEach(function(fn){
     this.use(fn);
   }, this);
   http.Server.call(this, this.handle);
 };
 /**
  * Inherit from `http.Server.prototype`.
  */
 Server.prototype.__proto__ = http.Server.prototype;

  “connect"是原型继承于"http server"的,它会用use到的中间件替换掉server的requestListener。

  通过"connect.use(route, handle)"来对每一个路由添加中间件,这些中间件"handle"会与"route"绑定保存在一个"stack"里面,每次有"request"请求的时候,

  遍历这个堆,找到对应"route"的"handle",执行"handle",如果"handle"最后调用了"next()",就会继续寻找并执行下一个匹配的"handle"。

  通过封装"handle",可以很容易的在"connect"基础上添加更多的"middleware"。

 (4),最后看看"listen(8888)",它做些什么工作那?

    很简单,通过继承底层的Server对象,赋予了"listen"的功能,监听特定端口。

    Server.prototype.__proto__ = http.Server.prototype

 以下是”connect.js“的全部源码,为了节省篇幅,注释已全部删掉,如下图:

  补充一下:

复制代码代码如下:
 fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
   if (/\.js$/.test(filename)) {
     var name = filename.substr(0, filename.lastIndexOf('.'));
     exports.middleware.__defineGetter__(name, function(){
       return require('./middleware/' + name);
     });
   }
 });

  将"middleware"对象"exports",然后循环定义给"middleware"对象一种方法,这种方法是直接加载 "middleware" 文件夹中的.js文件模块。

利用:"exports.utils.merge(exports, exports.middleware)" 这句话将middleware中的方法直接exports了。

三,总结一下:

   (1),理解源码的设计意图,有助于在应用上得到最大化的收获。

   (2),看源码时,理解流程再去扣语法细节。

   (3),借鉴源码中的巧妙实现思想,但不要过渡设计,为了设计而设计。

   (4),明天继续分析相关中间件,不断更新中 。。。 。。。

NodeJS学习笔记之Connect中间件模块(二)的更多相关文章

  1. NodeJS学习笔记之Connect中间件模块(一)

    NodeJS学习笔记之Connect中间件模块(一) http://www.jb51.net/article/60430.htm NodeJS学习笔记之Connect中间件模块(二) http://w ...

  2. NodeJS学习笔记之Connect中间件应用实例

    一,开篇分析 大家好哦,大熊君又来了,昨天因为有点个人的事没有写博客,今天又出来了一篇,这篇主要是写一个记事本的小应用,前面的文章, 我也介绍过“Connect”中间件的使用以及“Mongodb”的用 ...

  3. Nodejs学习笔记(三)--- 模块

    目录 简介及资料 自定义模块 创建一个自定义模块 调用自定义模块 exports和module.exports 区别 exports和module.exports 覆盖 其它... 简介及资料 通过N ...

  4. Nodejs学习笔记(三)—模块

    简介及资料 通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名') ...

  5. nodejs学习笔记之包、模块实现

        简单了解了node的安装和一些基本的常识之后,今天学习了node中很重要的包和模块的一些知识点.       首先学习一下包的规范,它由包结构和包描述两部分组成.包结构用于组织包的各种文件,包 ...

  6. NodeJS学习笔记 (27)实用工具模块-util(ok)

    debuglog(section) 很有用的调试方法.可以通过 util.debuglog(name) 来创建一个调试fn,这个fn的特点是,只有在运行程序时候,声明环境变量NODE_DEBUG=na ...

  7. NodeJS学习笔记 进阶 (12)Nodejs进阶:crypto模块之理论篇

    个人总结:读完这篇文章需要30分钟,这篇文章讲解了使用Node处理加密算法的基础. 摘选自网络 Nodejs进阶:crypto模块之理论篇 一. 文章概述 互联网时代,网络上的数据量每天都在以惊人的速 ...

  8. Nodejs学习笔记(二)——Eclipse中运行调试Nodejs

    前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...

  9. Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识

    目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...

随机推荐

  1. 在C#.NET中,如何生成PDF文件?主要有以下几个途径

    1.使用.NET文件流技术:若通过.NET的文件流技术生成PDF文件,必须对PDF文件的语法很清楚,例如BT表示实体内容开始:ET表示实体内容结束:TD表示换行等等.我们可以从Adobe的官方网站上下 ...

  2. 6、通过Appium Desktop 实现录制功能

    1.老规矩,我们进入下面这个界面 图中红色标记1为 “top by coordinates”  按钮, 这是一种通过坐标定位元素的方式. 图中红色标记2为 “Start Recording”  按钮, ...

  3. 解决Office 2010 每次打开word时出现配置进度框

    来自百度经验 装好Office 2010后,每次打开都会出现配置进度框,很烦人,怎么办呢 确认你的10版Office已激活,激活状态如图(激活工具一般在你下载的安装包里都有) 直接在”开始“运行框里输 ...

  4. 剑指offer——41数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  5. Linux apache httpd virtual配置

    必须要关闭 selinux,否则无法访问目录

  6. 通过字体代替图片优化,如何使用Font Awesome字体图标?

    博客搬迁,给你带来的不便敬请谅解! http://www.suanliutudousi.com/2017/10/17/%E9%80%9A%E8%BF%87%E5%AD%97%E4%BD%93%E4%B ...

  7. MySQL在Win10与Ubuntu下的安装与配置

        本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog     近段时间把自己电脑(win).虚拟机(Ubun ...

  8. 【牛客提高训练营2B】分糖果

    题目 发现自己一年之前非常垃圾 题目大意是给你一个\(n\)个点的环,给每个点一个\([1,a_i]\)的取值,并且满足环上任意相连两点权值不能相等,求方案数 考虑断环为链,发现不大会 不妨考虑所有\ ...

  9. 总分 Score Inflation

    题目背景 学生在我们USACO的竞赛中的得分越多我们越高兴. 我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助 题目描述 我们可以从几个种类中选取竞赛的题目,这里的一个"种类& ...

  10. 第十一篇 session和cookie自动登录机制

    session和cookie的作用和区别可以在网上查到,这里简单说下,我们使用的http协议本身是种无状态的协议,就是说web服务器接收到浏览器的请求,会直接返回相应内容,并不会检查是哪个浏览器,即浏 ...