_router
目标介绍
_router
目标是一个私有的特点,可是它保存了重要的内容。其间就包含一切的合理的 Layer 目标以及其他的。它对咱们剖析 express 运转脉络有很重要的效果。
运用调试直观的获取 _router
目标
要调试就需求预备以下的内容:
- 一个简略的能运转的 express demo。
- 运用 vscode 编辑器进行调试。
- 在适宜的当地打上断点并发动带有断点的服务。
- 调查悉数特点并找到
_router
目标以及特点。 - 找出 stack.layer 的摆放次序得出
- 剖析
_router
的嵌套目标
一个简略的可以运转的 demo
-
index.js
是程序的进口文件:
import express from 'express'
const app = express()
app.get('/', (_, res)=> {
res.json({
ab: 123,
})
})
app.get('/abc', () => {
res.send('x')
})
app.listen(3232, () => {
console.log("Listen on port 3232")
})
app 上运用了 get 办法增加了两个路由:
-
/
: 呼应一个 json -
/abc
: 呼应一个字符串
然后监听在 3232
端口。
运用 vscode 初始化一个调试文件
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/index.js"
}
]
}
调试文件会以 ${workspaceFolder}/index.js
为进口发动 express 服务,在 vscode 侧边栏找到调试项目,开始调试。
在适宜的地点打一个断点
哪里适宜?
当然是在 listen 之前最为适宜,此时 express 内部工作已经基本完成,只需求监听端口等候请求到来。
发动服务
运用 vscode 调试装备与调试工具发动服务
调查悉数特点并找到 _router
目标以及特点
- 调查悉数特点
因为 express 创建 app, 混入了许多的特点和办法所以需求对其进行有基本的认识,其间被本文重视的 _router
是需求要点重视的
-
_router
目标
_router
目标特点比较简略,其间需求重视的便是 stack
特点,因为 stack 特点后期会被遍历取出 layer 来获取 handle 履行函数。
找出 stack.layer 的摆放次序
layer 的次序如下:
-
query
: 内置 query 中间件发生 -
expressInit
: 内置 exressInit 中间件发生 -
boundDispatch 1
: get 路由/
发生 -
boundDispatch 2
: get 路由/abc
发生 -
_router
的 stack 目标存储的 Layer 实例,不是 route 目标的不增加 layer.route 为空:
以 query 内置中间件为例, route 是 undefined,表明不是路由,反之。
- 手动增加的路由 router 目标,保存了自己的 route 信息
- path
- stack
- methods
- …
route 中保存了自己的 stack 特点,stack 保存归于本路由的 layer, 暂且称之为 routeLayer, routeLayer 实例中坚持了 handle 办法,这个办法便是咱们在 express 中写的最多
的路由处理函数。
剖析 _router
的嵌套目标
_router
目标是 app 目标的特点,是整个目标的路由特点。
-
_router.stack
存储了一切的RouterLayer
目标,stack 中RouterLayer
有自己的增加次序,内置 query/expressInit 中间件被首要增加,然后是手动增加的路由和中间件。 -
RouterLayer
中存在 route 特点,纯中间件 route 特点为未定义,路由相关中间件 route 指向 Route 实例目标。app -> _router -> stack -> routerLayer[] -> routerLayer/routerLayer.route -> route.stack -> routeLayer[]/-> routeLayer/routeLayer.handle
。
_router
目标的相关源码
app.lazyrouter = function lazyrouter() {
if (!this._router) {
this._router = new Router({
caseSensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing')
});
this._router.use(query(this.get('query parser fn')));
this._router.use(middleware.init(this));
}
};
_router
函数在 lazyrouter 函数中被完成,并且是懒完成(有了就不在重新完成了),完成之后立即增加两个中间件。本质便是一个 Router 类的实例。
_router
的数据结构剖析
-
_router
不是顶层数据,app 才是。 -
_router
中保存了 router 相关的重要数据。stack 特点中保存一切的 routerlayer 层级数据。 -
_router.stack
的每一个 layer 中 route 特点一个有用路由数据。 -
route
中也保存了 stack route 层的 layer 数据。 -
route
层级的 layer 保存了 handle 和 handle 的参数 -
_router
数据结构中嵌套两个栈一个是 router.stack 栈,一个是 route.stack 栈,保存自己层级的数据。 -
handle
作为底层路由的处理函数,被保存在 route.stack 的 layer 中
_router
中包含 router 和 route 层,每一层都自己的 stack, router 层与 route 层经过 stack 的 layer 中的 route 特点链接,route 与 handle 函数链接经过 route 中 stack 储存的 layer 的 handle 特点链接,这就构成一个 _router
的数据结构:
小结
本文首要重视 _router 目标
,以及其 vscode 调试办法,特点层级和对应数据结构。熟悉其内部源码完成。
重视公踪号
进二开物
,更多 JS/TS/CSS/Rust 技术和科技讯息文章…