.6-浅析express源码之Router模块(2)-router.use

匿名 (未验证) 提交于 2019-12-02 21:53:52

  这一节继续深入Router模块,首先从最常用的use开始。

 

router.use

  方法源码如下:

proto.use = function use(fn) {     var offset = 0;     var path = '/';      if (typeof fn !== 'function') {         var arg = fn;         while (Array.isArray(arg) && arg.length !== 0) arg = arg[0];         if (typeof arg !== 'function') {             offset = 1;             path = fn;         }     }      var callbacks = flatten(slice.call(arguments, offset));      if (callbacks.length === 0) throw new TypeError('Router.use() requires a middleware function')      for (var i = 0; i < callbacks.length; i++) {         var fn = callbacks[i];          if (typeof fn !== 'function') throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))          debug('use %o %s', path, fn.name || '<anonymous>');         // 内部模块layer!         var layer = new Layer(path, {             sensitive: this.caseSensitive,             strict: false,             end: false         }, fn);         // 通过use方法生成的layer没有route值         layer.route = undefined;         // 初始化时定义的数组         this.stack.push(layer);     }      return this; };

  前半部分十分熟悉,根本就是app.use的翻版。

  当然,最后遍历中间件函数处理的时候就不一样了,引入了新的本地模块Layer。

 

Layer

  不太理解这个层的意义,无论是app.use还是router.use,每一个中间件都会生成一个layer对象,然后push进router上的stack数组。

  那么多路径呢,是否会生成多个layer?答案是否。

  看一眼layer的构造函数:

function Layer(path, options, fn) {     if (!(this instanceof Layer)) {         return new Layer(path, options, fn);     }      debug('new %o', path)     var opts = options || {};     /**      * layer.handle => 中间件函数      * layer.name => 函数名      * layer.regexp => 路径的正则      */     this.handle = fn;     this.name = fn.name || '<anonymous>';     this.params = undefined;     this.path = undefined;     this.regexp = pathRegexp(path, this.keys = [], opts);      // 快速匹配标记     this.regexp.fast_star = path === '*'     this.regexp.fast_slash = path === '/' && opts.end === false }

  其中比较关键一步是根据传进来的path生成一个正则,pathRegexp是一个工具模块,无论传进去的是字符串、数组、正则都能返回一个正则匹配需要的值。

  简略的看一下工具核心源码:

function pathtoRegexp(path, keys, options) {     // ...      // 字符串     path = ('^' + path + (strict ? '' : path[path.length - 1] === '/' ?  
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!