关于express路由的一些疑问

发布于 2022-09-06 10:10:21 字数 582 浏览 9 评论 0

//users.js
var express = require('express');
var router = express.Router();

//路由定义
router.get('/article', function(req, res) {
    res.render('index', {titile: 'express'});
};
//模块导出
module.exports = router;


//app.js
var user = require(./routes/users');
app.use('/users', user);

请问express是如何做到路由匹配的,在看express源码时候看到routes是个handle(req, res, next)方法,_route->stack->layer, 而get等方法是_route->stack->layer->route->stack->layer,
第一个问题是想问调用好中间件方法之后/article,是如何做到匹配的?第二个问题是因为listen监听的是app()里面的handle函数,如何做到路由的实时监听,比如网页上写了一个地址,如何触发的,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹过旳痕迹 2022-09-13 10:10:21

express为了做到灵活、代码精简,内部的代码进行了大量的抽象+复用,尤其是在路由这块。楼主看了心生疑惑是正常的,这块的代码的确挺糟糕的。

楼主的问题足够写一篇很长的文章,编写回答将近半个小时候我觉得放弃有条理的回答,直奔主题。

// 楼主的代码,稍微精简下
var router = express.Router();
router.get('/article', fn);

// app的_router 属性,其实也是 express.Router()
app._router = new Router();
app._router.use('/user', router); 

// 上面的代码导致下面的逻辑
app._router.stack.push(new Layer({
  path: '/user',
  handler: fn,
  route: undefined // 这里!非常关键
));

// 请求到来时,假设 path 是 '/user'
app.handle() -> app._router.handle();

// 然后,遍历 app._router.stack 数组,看有没有那个 stack(里面是Layer实例)的path属性符合要求
// 如果找到符合要求的,也就是楼主的 router 

我们看下下面代码发生了什么

router.get('/article', fn);

在内部,往 stack 里又push了 Layer 实例。

var layer = new Layer({
  path: '/article',
  handler: fn
};
// 这里非常关键!这个实际存放路由,也就是 用户访问 /user/article 时的回调方法
layer.route = new Route();
router.stack.push(layer);

为什么楼主会觉得疑惑

前面说了,express这块的代码本身挺糟糕的,比如存在如下用法,并且内部都是往 router.stack 里新增一个 Layer实例

routerA.use(path, routerB); // 第一种 
routerA.get(path, fn); // 第二种

那么,如何区分是子路由,还是实际的路由

// 子路由,对应第一种
layer.route = undefined;
router.stack.push(layer);

// 实际路由,对应第二种
layer.route = new Route();
router.stack.push(layer);

如何匹配的

比如楼主访问了 /user/articles,那么express内部(跳过一些琐碎的分支判断)

  1. 查看有没有匹配 /user 的子路由,发现有,就是楼主的 router。实际动作是搜索 app._router.stack
  2. 查看有没有匹配 /articles 的实际路由,发现有。实际动作是搜索 router.stack[i].layer,并且找到对应的处理方法 router.stack[i].layer.route[i].stack

express为了做到灵活、代码精简,内部的代码进行了大量的抽象+复用,尤其是在路由这块。楼主看了心生疑惑是正常的,这块的代码的确挺糟糕的。

楼主的问题足够写一篇很长的文章,编写回答将近半个小时候我觉得放弃有条理的回答,直奔主题。

// 楼主的代码,稍微精简下
var router = express.Router();
router.get('/article', fn);

// app的_router 属性,其实也是 express.Router()
app._router = new Router();
app._router.use('/user', router); 

// 上面的代码导致下面的逻辑
app._router.stack.push(new Layer({
  path: '/user',
  handler: fn,
  route: undefined // 这里!非常关键
));

// 请求到来时,假设 path 是 '/user'
app.handle() -> app._router.handle();

// 然后,遍历 app._router.stack 数组,看有没有那个 stack(里面是Layer实例)的path属性符合要求
// 如果找到符合要求的,也就是楼主的 router 

我们看下下面代码发生了什么

router.get('/article', fn);

在内部,往 stack 里又push了 Layer 实例。

var layer = new Layer({
  path: '/article',
  handler: fn
};
// 这里非常关键!这个实际存放路由,也就是 用户访问 /user/article 时的回调方法
layer.route = new Route();
router.stack.push(layer);

为什么楼主会觉得疑惑

前面说了,express这块的代码本身挺糟糕的,比如存在如下用法,并且内部都是往 router.stack 里新增一个 Layer实例

routerA.use(path, routerB); // 第一种 
routerA.get(path, fn); // 第二种

那么,如何区分是子路由,还是实际的路由

// 子路由,对应第一种
layer.route = undefined;
router.stack.push(layer);

// 实际路由,对应第二种
layer.route = new Route();
router.stack.push(layer);

如何匹配的

比如楼主访问了 /user/articles,那么express内部(跳过一些琐碎的分支判断)

  1. 查看有没有匹配 /user 的子路由,发现有,就是楼主的 router。实际动作是搜索 app._router.stack
  2. 查看有没有匹配 /articles 的实际路由,发现有。实际动作是搜索 router.stack[i].layer,并且找到对应的处理方法 router.stack[i].layer.route[i].stack
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文