NodeJS学习笔记之Connect中间件模块(二)


Posted in NodeJs onJanuary 27, 2015

一,开篇分析

大家好,今天这篇文章主要是对"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“的全部源码,为了节省篇幅,注释已全部删掉,如下图:

NodeJS学习笔记之Connect中间件模块(二)

补充一下:

 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 相关文章推荐
使用NodeJs 开发微信公众号(三)微信事件交互实例
Mar 02 NodeJs
Nodejs Stream 数据流使用手册
Apr 17 NodeJs
深入nodejs中流(stream)的理解
Mar 27 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
nodejs操作mysql实现增删改查的实例
May 28 NodeJs
NodeJS链接MySql数据库的操作方法
Jun 27 NodeJs
基于nodejs+express4.X实现文件下载的实例代码
Jul 13 NodeJs
NodeJs form-data格式传输文件的方法
Dec 13 NodeJs
nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例
Jan 05 NodeJs
nodejs+mongodb aggregate级联查询操作示例
Mar 17 NodeJs
nodejs基础之多进程实例详解
Dec 27 NodeJs
nodejs+koa2 实现模仿springMVC框架
Oct 21 NodeJs
NodeJS学习笔记之Connect中间件模块(一)
Jan 27 #NodeJs
nodejs批量修改文件编码格式
Jan 22 #NodeJs
NodeJS学习笔记之MongoDB模块
Jan 13 #NodeJs
NodeJS学习笔记之(Url,QueryString,Path)模块
Jan 13 #NodeJs
NodeJS学习笔记之FS文件模块
Jan 13 #NodeJs
NodeJS学习笔记之Http模块
Jan 13 #NodeJs
Nodejs学习笔记之Stream模块
Jan 13 #NodeJs
You might like
php 解决旧系统 查出所有数据分页的类
2012/08/27 PHP
给ECShop添加最新评论
2015/01/07 PHP
php 输入输出流详解及示例代码
2016/08/25 PHP
PHP 记录访客的浏览信息方法
2018/01/29 PHP
浅谈laravel-admin的sortable和orderby使用问题
2019/10/03 PHP
thinkphp框架表单数组实现图片批量上传功能示例
2020/04/04 PHP
Jquery从头学起第四讲 jquery入门教程
2010/08/01 Javascript
IE的事件传递-event.cancelBubble示例介绍
2014/01/12 Javascript
AngularJS入门教程(零):引导程序
2014/12/06 Javascript
js的window.showModalDialog及window.open用法实例分析
2015/01/29 Javascript
jQuery实现鼠标划过添加和删除class的方法
2015/06/26 Javascript
js HTML5 Canvas绘制转盘抽奖
2020/09/13 Javascript
jQuery和JavaScript节点插入元素的方法对比
2016/11/18 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
微信JSAPI支付操作需要注意的细节
2017/01/10 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
vue中如何让子组件修改父组件数据
2018/06/14 Javascript
微信小程序性能优化之checkSession的使用
2019/03/06 Javascript
微信小程序间使用navigator跳转传值问题实例分析
2020/03/27 Javascript
ES5和ES6中类的区别总结
2020/12/21 Javascript
python基础教程之自定义函数介绍
2014/08/29 Python
Pycharm更换python解释器的方法
2018/10/29 Python
Python语法分析之字符串格式化
2019/06/13 Python
Trunki英国官网:儿童坐骑式行李箱
2017/05/30 全球购物
吉尔德利巧克力公司:Ghirardelli Chocolate Company
2019/03/27 全球购物
俄罗斯品牌服装和鞋子的在线商店:KUPIVIP
2019/10/27 全球购物
关于毕业的广播稿
2014/01/10 职场文书
市场营销专业毕业生求职信
2014/07/21 职场文书
国企干部对照检查材料
2014/08/22 职场文书
奥巴马上海演讲稿
2014/09/10 职场文书
镇政府副镇长群众路线专题民主生活会对照检查材料
2014/09/19 职场文书
小学英语教学随笔
2015/08/14 职场文书
基于Redis延迟队列的实现代码
2021/05/13 Redis
请求模块urllib之PYTHON爬虫的基本使用
2022/04/08 Python
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js