Express框架中_router?對象數(shù)據(jù)結(jié)構(gòu)使用詳解
_router 對象介紹
_router 對象是一個私有的屬性,但是它保存了重要的內(nèi)容。其中就包括所有的合理的 Layer 對象以及其他的。它對我們分析 express 運行脈絡(luò)有很重要的作用。
使用調(diào)試直觀的獲取 _router 對象
要調(diào)試就需要準備以下的內(nèi)容:
- 一個簡單的能運行的 express demo。
- 使用 vscode 編輯器進行調(diào)試。
- 在合適的地方打上斷點并啟動帶有斷點的服務(wù)。
- 觀察全部屬性并找到 _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 方法添加了兩個路由:
- /: 響應(yīng)一個 json
- /abc: 響應(yīng)一個字符串
然后監(jiān)聽在 3232 端口。
使用 vscode 初始化一個調(diào)試文件
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/index.js"
}
]
}
調(diào)試文件會以 ${workspaceFolder}/index.js 為入口啟動 express 服務(wù),在 vscode 側(cè)邊欄找到調(diào)試項目,開始調(diào)試。
在合適的地點打一個斷點
哪里合適?
當然是在 listen 之前最為合適,此時 express 內(nèi)部工作已經(jīng)基本完成,只需要監(jiān)聽端口等待請求到來。

啟動服務(wù)

使用 vscode 調(diào)試配置與調(diào)試工具啟動服務(wù)
觀察全部屬性并找到 _router 對象以及屬性
- 觀察全部屬性

由于 express 創(chuàng)建 app, 混入了很多的屬性和方法所以需要對其進行有基本的認識,其中被本文關(guān)注的 _router 是需要重點關(guān)注的
- _router對象

_router 對象屬性比較簡單,其中需要關(guān)注的就是 stack 屬性,因為 stack 屬性后期會被遍歷取出 layer 來獲取 handle 執(zhí)行函數(shù)。
找出 stack.layer 的排列順序

layer 的順序如下:
- query: 內(nèi)置 query 中間件產(chǎn)生
- expressInit: 內(nèi)置 exressInit 中間件產(chǎn)生
- boundDispatch 1: get 路由 / 產(chǎn)生
- boundDispatch 2: get 路由 /abc 產(chǎn)生
- _router 的 stack 對象存儲的 Layer 實例,不是 route 對象的不添加 layer.route 為空:

以 query 內(nèi)置中間件為例, route 是 undefined,表示不是路由,反之。
- 手動添加的路由 router 對象,保存了自己的 route 信息

- path
- stack
- methods
- ...

route 中保存了自己的 stack 屬性,stack 保存屬于本路由的 layer, 暫且稱之為 routeLayer, routeLayer 實例中保持了 handle 方法,這個方法就是我們在 express 中寫的最多的路由處理函數(shù)。

分析 _router 的嵌套對象
_router 對象是 app 對象的屬性,是整個對象的路由屬性。
- _router.stack 存儲了所有的 RouterLayer 對象,stack 中 RouterLayer 有自己的添加順序,內(nèi)置 query/expressInit 中間件被首先添加,然后是手動添加的路由和中間件。
- RouterLayer 中存在 route 屬性,純中間件 route 屬性為未定義,路由相關(guān)中間件 route 指向 Route 實例對象。app -> _router -> stack -> routerLayer[] -> routerLayer/routerLayer.route -> route.stack -> routeLayer[]/-> routeLayer/routeLayer.handle。
_router 對象的相關(guān)源碼
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 函數(shù)在 lazyrouter 函數(shù)中被實現(xiàn),并且是懶實現(xiàn)(有了就不在重新實現(xiàn)了),實現(xiàn)之后立即添加兩個中間件。本質(zhì)就是一個 Router 類的實例。
_router 的數(shù)據(jù)結(jié)構(gòu)分析
- _router 不是頂層數(shù)據(jù),app 才是。
- _router 中保存了 router 相關(guān)的重要數(shù)據(jù)。stack 屬性中保存所有的 routerlayer 層級數(shù)據(jù)。
- _router.stack 的每一個 layer 中 route 屬性一個有效路由數(shù)據(jù)。
- route 中也保存了 stack route 層的 layer 數(shù)據(jù)。
- route 層級的 layer 保存了 handle 和 handle 的參數(shù)
- _router 數(shù)據(jù)結(jié)構(gòu)中嵌套兩個棧一個是 router.stack 棧,一個是 route.stack 棧,保存自己層級的數(shù)據(jù)。
- handle 作為底層路由的處理函數(shù),被保存在 route.stack 的 layer 中
_router 中包含 router 和 route 層,每一層都自己的 stack, router 層與 route 層通過 stack 的 layer 中的 route 屬性鏈接,route 與 handle 函數(shù)鏈接通過 route 中 stack 儲存的 layer 的 handle 屬性鏈接,這就構(gòu)成一個 _router 的數(shù)據(jù)結(jié)構(gòu):

小結(jié)
本文主要關(guān)注 _router 對象,以及其 vscode 調(diào)試方法,屬性層級和對應(yīng)數(shù)據(jù)結(jié)構(gòu)。熟悉其內(nèi)部源碼實現(xiàn)。
以上就是Express框架中_router 對象數(shù)據(jù)結(jié)構(gòu)使用詳解的詳細內(nèi)容,更多關(guān)于Express _router 對象數(shù)據(jù)結(jié)構(gòu)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解JS中的compose函數(shù)和pipe函數(shù)用法
這篇文章主要介紹了JS中的compose函數(shù)和pipe函數(shù)用法,想深入了解Javascript的同學(xué),可以參考下2021-04-04
uni-app使用Vite.config.js配置文件的超詳細教程
這篇文章主要給大家介紹了關(guān)于uni-app使用Vite.config.js配置文件的超詳細教程,在uniapp開發(fā)中,vue.config.js是配置webpack的關(guān)鍵文件之一,也可以說是uniapp項目自定義配置的中心,需要的朋友可以參考下2023-12-12
Windows Live的@live.com域名注冊漏洞 利用代碼
Windows Live的@live.com域名注冊漏洞 利用代碼...2006-12-12

