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

    express/appliction.js

    application.js对外的方法可以分成四类:

    • 设置/初始化成员变量,主要是对成员变量settings进行设置,这样的方法有:enabled、enabled、disabled、 disable和set方法。
    • 设置路由和对每个路由设置中间件:这样的方法有:use.router,all,param和methods方法。
    • 设置模板引擎的方法:engine和render。
    • 启动node服务器对res和req操作的方法:listen和handler。

    1.解析app.engine方法

    express的api中有app.engine方法,例如:

    app.engine("handlebars",handlebars.engine);

    看下这个函数的的核心代码就是:

     // get file extension,ext为文件扩展名
      var extension = ext[0] !== '.'
        ? '.' + ext
        : ext;
    
      // store engine
      this.engines[extension] = fn;

     1.2 解析app.use方法

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

    进入app.user源码:

    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数组中。
    this._router.use(query(this.get('query parser fn'))); 
        //this.get('query parser fn')为一个函数:
        this._router.use(middleware.init(this));
       }
    };  

    看看router的构造函数,它在express/lib/router/index.js文件中,express功能核心都在这个文件,它的定义和app的定义很类似。

     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);

    同理:this._router.use(middleware.init(this))的作用是把该函数,构造成一个Layer成员,然后是给router.stack添加一个layer成员。

    //middleware.init(this)返回的是下列函数:
    return
    function expressInit(req, res, next){ if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); req.res = res; res.req = req; req.next = next; req.__proto__ = app.request; res.__proto__ = app.response; res.locals = res.locals || Object.create(null); next(); };

    在express初始的时候,router的stack数组中有两个回调函数了。所有调用app.user(fn),都是给rounter的stack数组中添加回调函数,

    express中的路由机制,可以参考链接:http://cnodejs.org/topic/545720506537f4d52c414d87,里面说的非常具体!

  • 相关阅读:
    linq判断集合是否为空的方法
    MVC控制器取参数值
    linq查询结果转换为指定字段类型的list集合
    C#Web异步操作封装
    js基础细节
    写入临时日志到文本
    css3超过指定宽度文字,显示省略号
    如何判断Javascript对象是否存在
    chrome下input[type=text]的placeholder不垂直居中的问题解决
    sqlserver临时表操作
  • 原文地址:https://www.cnblogs.com/liuyinlei/p/6118119.html
Copyright © 2011-2022 走看看