首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >express的application.js里的路由代码

express的application.js里的路由代码

作者头像
theanarkh
发布2019-03-06 10:59:39
2.8K0
发布2019-03-06 10:59:39
举报
文章被收录于专栏:原创分享原创分享原创分享

application.js是express框架的核心,也是里面包括了服务端的很多配置和逻辑代码。这里主要说一下和路由有关的一些代码。

app.handle = function handle(req, res, callback) {
  var router = this._router;//这里一开始是空的,只有使用app的http verb方法或者use方法时才会去惰性加载

  // final handler
  var done = callback || finalhandler(req, res, {
    env: this.get('env'),
    onerror: logerror.bind(this)
  });

  // no routes
  if (!router) {//这里一开始是空的,只有使用app的http verb方法或者use方法时才会去惰性加载
    debug('no routes defined on app');
    done();
    return;
  }

  router.handle(req, res, done);
};

app.use = function use(fn) {
  var offset = 0;
  var path = '/';

  // default path to '/'
  // disambiguate app.use([fn])
  if (typeof fn !== 'function') {
    var arg = fn;

    while (Array.isArray(arg) && arg.length !== 0) {
      arg = arg[0];
    }

    // first arg is the path
    if (typeof arg !== 'function') {
      offset = 1;
      path = fn;
    }
  }

  var fns = flatten(slice.call(arguments, offset));

  if (fns.length === 0) {
    throw new TypeError('app.use() requires middleware functions');
  }

  // setup router
  this.lazyrouter();
  var router = this._router;

  fns.forEach(function (fn) {//每一个fn对应一个Layer,所以app.use(fn)时,无论是同时传入多个参数还是多次使用use,每个函数或中间件都对应一个Layer
    // non-express app
    if (!fn || !fn.handle || !fn.set) {//fn是函数时
      return router.use(path, fn);
    }
    //fn是路由对象route时
    debug('.use app under %s', path);
    fn.mountpath = path;
    fn.parent = this;

    // restore .app property on req and res
    router.use(path, function mounted_app(req, res, next) {//app.use('/',router);
      var orig = req.app;
      fn.handle(req, res, function (err) {
        req.__proto__ = orig.request;
        res.__proto__ = orig.response;
        next(err);
      });
    });

    // mounted an app
    fn.emit('mount', this);
  }, this);

  return this;
};

app.route = function route(path) {
  this.lazyrouter();
  return this._router.route(path);
};

app.all = function all(path) {
  this.lazyrouter();

  var route = this._router.route(path);
  var args = slice.call(arguments, 1);

  for (var i = 0; i < methods.length; i++) {
    route[methods[i]].apply(route, args);
  }

  return this;
};

1.app.handle是服务器的逻辑入口,其实然后直接通过router.handle进入到路由的查找和处理,这个查找和处理过程在上一章里已经分析过,也就是开始对router二维数组进行查找的过程。

2.app.route函数是直接通过app来配置路由的一个快捷方式,他的本质是利用了router.route方法,这个方法会让路由形成一个二维数组的结构。而不是一维数组。

3.app.use的本质是调用router的方法进行处理,就是把传入的函数挂载到layer层,然后储存在router的stack中,其中有一个特殊的情况需要处理,就是如果用户传入了一个router类型的路由对象的时候,这时候,如果匹配了对应的路径时,执行的是该路由对象的handle方法,然后进入该router对象的内部处理逻辑。和下面的all方法是不一样的。

4.app.all方法本质是利用route对象进行配置路由,逻辑是一个两层的循环,先是method数组的循环,然后是在route中具体的http方法函数里的循环。 这会在一个route对象的stack数组中存储大量的layer。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档