zoukankan      html  css  js  c++  java
  • 大熊君大话NodeJS之 ------ Connect中间件第二季(源码分析)

    一,开篇分析

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

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

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

      

    1 var connect = require("./lib/connect") ;
    2 var app = connect.createServer() ;
    3 app.use(connect.static(__dirname + "/public",{
    4     maxAge: 0 
    5 })) ;
    6 app.use(function(req,res,next){
    7     res.end("Hello World !") ;
    8 })
    9 .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,大雄君 !
    ")  ;
    }).listen(8888)  ; // 2

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

      

    exports = module.exports = createServer ;
    
    exports.createServer = createServer ;

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

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

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

     1 var HTTPServer = require('./http').Server , 
     2 HTTPSServer = require('./https').Server ;
     3 
     4 function createServer() {
     5   if ('object' == typeof arguments[0]) {
     6     return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1));
     7   } else {
     8     return new HTTPServer(Array.prototype.slice.call(arguments));
     9   }
    10 };

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

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

     1 var Server = exports.Server = function HTTPServer(middleware) {
     2   this.stack = [];
     3   middleware.forEach(function(fn){
     4     this.use(fn);
     5   }, this);
     6   http.Server.call(this, this.handle);
     7 };
     8 
     9 /**
    10  * Inherit from `http.Server.prototype`.
    11  */
    12 
    13 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“的全部源码,为了节省篇幅,注释已全部删掉,如下图:

      

      补充一下:

        

    1 fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
    2   if (/.js$/.test(filename)) {
    3     var name = filename.substr(0, filename.lastIndexOf('.'));
    4     exports.middleware.__defineGetter__(name, function(){
    5       return require('./middleware/' + name);
    6     });
    7   }
    8 });

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

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

      三,总结一下:

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

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

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

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

                       哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)       

  • 相关阅读:
    中英文对照 —— 宗教
    十万个为什么 —— 冷知识
    十万个为什么 —— 冷知识
    OpenCV调试利器——Image Watch插件的安装和使用
    matlab 读写其他格式数据文件(excel)
    matlab 读写其他格式数据文件(excel)
    文学创作的艺术手法
    文学创作的艺术手法
    常用cl命令参数解释
    网站的栏目和目录结构规划方法
  • 原文地址:https://www.cnblogs.com/bigbearbb/p/4224290.html
Copyright © 2011-2022 走看看