• express源码剖析--Router模块和Layer模块


    Router模块

    1.加载模块执行代码:

    methods.forEach(function(method){
      //method是http协议的各种请求方法,如:get,put,headee,post
      Route.prototype[method] = function(){
          ....为method的各种方法构造一个Layer,并且放入stack数组中
      };
    });
    //其实router.all()的功能和methods的功能差不多。

    methods方法包含有:

    function getBasicNodeMethods() {
      return [
        'get',
        'post',
        'put',
        'head',
        'delete',
        'options',
        'trace',
        'copy',
        'lock',
        'mkcol',
        'move',
        'purge',
        'propfind',
        'proppatch',
        'unlock',
        'report',
        'mkactivity',
        'checkout',
        'merge',
        'm-search',
        'notify',
        'subscribe',
        'unsubscribe',
        'patch',
        'search',
        'connect'
      ];
    }

    2.构造函数

    function Route(path) {
      //三个成员, 路由的路径,方法对象。和储存对应的请求处理函数
      this.path = path;
      this.stack = [];
    
      debug('new %s', path);
    
      // route handlers for various http methods
      this.methods = {};
    }

    3.原型对象上方法

    Route.prototype ={
      /*返回boolean类型,判断router是否支持给定的method方法,有个特殊情况:当method时head,并且Router不支持head请求时,method改成get*/
       _handles_method:_handles_method(method),
      /*返回一个route所支持的HTTP请求的数组,特殊情况:如果请求时方法get支持,而head不支持,那么head也应该改成true*/
        _options:_options(),
      //遍历该Route的stack(不是Router)中所有的Layer,依次执行。递归来解决遍历,要注意的是:在fn执行错误之后抛出err,如果这个err === "route",那么结束遍历,否则继续,执行下一个fn,
       dispatch:function dispatch(req, res, done),
       //支持所有http请求,而且this.method._all为true。
       _all:function(){
       //layer.method = undefined;
       this.methods._all = true;
       }    
    }

    dispatch是在router.route方法中,初始化layer的时候绑定到Layer.handler上的,解析下dispatch代码:

       next();
      function next(err) {
        //执行layer.handle抛出route就不需要再遍历stack了。
        if (err && err === 'route') {
          return done();
        }
    
        var layer = stack[idx++];
        //stack遍历结束。
        if (!layer) {
          return done(err);             
        }
        //没有匹配到layer。
        if (layer.method && layer.method !== method) {
          return next(err);
        }
    
        if (err) {
          //处理错误。他可以改变err值,例如可以改变成route,让遍历stack结束。
          //也可以消除err,继续遍历。也可以是其他错误,继续遍历layer。
          layer.handle_error(err, req, res, next);
        } else {
          //执行完layer.handler, next(err);
          layer.handle_request(req, res, next);
        }

    Layer模块

     Layer.js作为中间件封装的数据结构,看Layer包的构造函数,

    function Layer(path, options, fn) {
      if (!(this instanceof Layer)) {
        // this是Layer的实例
        return new Layer(path, options, fn);
      }
      
      debug('new %s', path);
      var opts = options || {};
    
      this.handle = fn;
      this.name = fn.name || '<anonymous>';
      this.params = undefined;
      this.path = undefined;
      this.regexp = pathRegexp(path, this.keys = [], opts);
    
      if (path === '/' && opts.end === false) {
       
        this.regexp.fast_slash = true; 
      }
    } 

     该模块包含构造函数和原型上绑定三个功能方法:handle_error、handle_request和match。

     handle_error处理请求异常情况;handle_request处理请求正常情况;handler_request可能会抛出错误:

    try {
        fn(req, res, next);     
       //具体的err是由插件来决定的。
      } catch (err) {
        next(err);
      }

     match函数的返回值只有true和false, 当然也可能会抛出错误。

      // store values
      this.params = {};
      this.path = m[0]; //第一个元素是输入的路径,后面都是匹配的分组
      //this.keys是对path中参数的解释。如path="/user/:foo",:foo是请求中的参数,那么keys=[name:"foo",delimiter:"false"]
      var keys = this.keys;
      var params = this.params;
      for (var i = 1; i < m.length; i++) {
        var key = keys[i - 1];
        var prop = key.name;
        var val = decode_param(m[i]);
        //给this.params赋值
        if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
          params[prop] = val;
        }
      }
      return true;

     

    结构如上图:Route、Layer和Router三者的关系。

  • 相关阅读:
    HTML学习笔记
    JSP与Servlet的跳转及得到路径方法整理(转)
    Servlet 学习笔记6:Cookie
    工作=娱乐=爱[龙]
    幸福的方法[龙]
    10张海报,激励人生[龙]
    8个方法让你安然度过低效率的日子[龙]
    使用空余时间的20个有效途径
    人生三点钟
    2013计划
  • 原文地址:https://www.cnblogs.com/liuyinlei/p/6266185.html
Copyright © 2020-2023  润新知