zoukankan      html  css  js  c++  java
  • express源码剖析2

    使用express时,代码会这样写:

    var express = require('express');

    创建一个express的应用,代码:

    var app = express();

    那么express()是什么?它执行createApplication()

    //express.js
    exports = module.exports =createApplication;
    /**
     * Create an express application.
     *
     * @return {Function}
     * @api public
     */
    
    function createApplication() {
      var app = function(req, res, next) {
        app.handle(req, res, next);
      };
    
      mixin(app, EventEmitter.prototype, false);
      mixin(app, proto, false);
    
      app.request = { __proto__: req, app: app };
      app.response = { __proto__: res, app: app };
      app.init();
      return app;  
      //执行的结果就是app是一个实例,它有私有成员对象:request和 response,同时继承Event模块中的EventEmitter的原型。
    }

    在express.js中,要区分下面两个包:

    var Route = require('./router/route');
    var Router = require('./router');
    //对外都暴露Route和Router,他们两者有些不同,
    //Router是Route的超集,两者的联系只在Router.route用到。调用Router.route会得到一个route,不过给Router.stack添加了一个Layer,
    //该Layer通过Router的参数和route.dispatch和用户的path来定义的。
    //route只有三个成员,stack数组(储存Layer对象),path(路由的路径)和method对象。
    //其中stack数组与Router一样,同时两个对象的原型都有methods的和all的方法
    exports.Route = Route;
    exports.Router = Router;

    express也继承了application.js中的方法。执行app.init();

    app.init = function init() {
     //给app类/对象赋值三个公用成员, 在初始的过程中,有一个成员变量很关键,就是router
      this.cache = {};
      this.engines = {};
      this.settings = {};
      // 初始化配置,在研究defaultConfiguration之前,抽象下app.set函数,它就是给setting赋值的函数,同时针对key = "etag" 和 query parser以及"trust proxy"进行特殊的的设置。
      this.defaultConfiguration();
    };

    app还挂有很多方法,这些可以在express的api中的application的方法找到!其中最重要的方法是app.use,它用来构造路由所执行的函数的一个数据结构_router,express在执行过程中,会遍历这个结构。

     1.1app.use方法

    //use的使用
    var express = require('express');
    var app = express();
    function handlerWrap(){
        console.log("1");
    }
    app.use("/", handlerWrap);                //路径/会调用hanlerWrap方法

     app.use源码

    this.lazyrouter();  
    app.lazyrouter = function lazyrouter() {
    //给a公有变量_router赋值,它是对象Router的实例。
    if (!this._router) {
    //实例化Router
    this._router = new Router({
         caseSensitive: this.enabled('case sensitive routing'),   //false
         strict: this.enabled('strict routing')                   //false 
     });
    //router.use(path,fn);  为path建立layer,有多少个fn,就建立多少个Layer,然后把这个layer压入router.stack数组中。初始定义了两个Layer
    this._router.use(query(this.get('query parser fn'))); 
        //this.get('query parser fn')为一个函数:
        this._router.use(middleware.init(this));
       }
    };  
    if (!fn || !fn.handle || !fn.set) {
          //handlerWrap函数为handler、 set成员!,如果fn函数没有handle,或者set函数,调用router.use(path,fn)。也就是说那不是express的实例,大部分插件都会直接执行。
          return router.use(path, fn);  //rounter.use直接把该函数构造成一个Layer成员,实际上是给router.stack添加一个layer成员。
     }
     debug('.use app under %s', path);
     fn.mountpath = path;          //如果是express的对象,那么给express这个对象成员mountpath赋值为path(可能含有正则);
     fn.parent = this;             //fn变成子express对象,当前的express为父。
     // restore .app property on req and res   //执行use,封装了fn,
    router.use(path, function mounted_app(req, res, next) {
     var orig = req.app;               //这里看的不太懂。      
       fn.handle(req, res, function (err) {
         req.__proto__ = orig.request;
         res.__proto__ = orig.response;
         next(err);
         });
    });
    // mounted an app
    console.log("fn="+JSON.stringify(fn));
    fn.emit('mount', this);
     // 进入router/index.js中,执行proto.use()方法。
     // 实际上是给router.stack添加一个layer成员,
      var layer = new Layer(path, {
        sensitive: this.caseSensitive,
        strict: false,
        end: false
      }, fn);
      layer.route = undefined;  //给layer.route赋值undefined
       this.stack.push(layer);

     

  • 相关阅读:
    iOS UITextField限制输入长度
    SpringBoot 统一异常处理
    idea+springboot+freemarker热部署
    JAVA 实现链表
    mysql 添加新用户 赋予权限
    Spring MVC 集成 Redis集群
    js获取当前日期时间及其它操作
    MySQL Error Codes MYSQL的错误代码
    js数组 删除元素
    JS table form 序列化提交
  • 原文地址:https://www.cnblogs.com/liuyinlei/p/6264677.html
Copyright © 2011-2022 走看看