Express框架中_router?對(duì)象數(shù)據(jù)結(jié)構(gòu)使用詳解
_router 對(duì)象介紹
_router 對(duì)象是一個(gè)私有的屬性,但是它保存了重要的內(nèi)容。其中就包括所有的合理的 Layer 對(duì)象以及其他的。它對(duì)我們分析 express 運(yùn)行脈絡(luò)有很重要的作用。
使用調(diào)試直觀的獲取 _router 對(duì)象
要調(diào)試就需要準(zhǔn)備以下的內(nèi)容:
- 一個(gè)簡(jiǎn)單的能運(yùn)行的 express demo。
- 使用 vscode 編輯器進(jìn)行調(diào)試。
- 在合適的地方打上斷點(diǎn)并啟動(dòng)帶有斷點(diǎn)的服務(wù)。
- 觀察全部屬性并找到 _router 對(duì)象以及屬性。
- 找出 stack.layer 的排列順序得出
- 分析 _router 的嵌套對(duì)象
一個(gè)簡(jiǎn)單的可以運(yùn)行的 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 方法添加了兩個(gè)路由:
- /: 響應(yīng)一個(gè) json
- /abc: 響應(yīng)一個(gè)字符串
然后監(jiān)聽(tīng)在 3232 端口。
使用 vscode 初始化一個(gè)調(diào)試文件
{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}/index.js" } ] }
調(diào)試文件會(huì)以 ${workspaceFolder}/index.js 為入口啟動(dòng) express 服務(wù),在 vscode 側(cè)邊欄找到調(diào)試項(xiàng)目,開(kāi)始調(diào)試。
在合適的地點(diǎn)打一個(gè)斷點(diǎn)
哪里合適?
當(dāng)然是在 listen 之前最為合適,此時(shí) express 內(nèi)部工作已經(jīng)基本完成,只需要監(jiān)聽(tīng)端口等待請(qǐng)求到來(lái)。
啟動(dòng)服務(wù)
使用 vscode 調(diào)試配置與調(diào)試工具啟動(dòng)服務(wù)
觀察全部屬性并找到 _router 對(duì)象以及屬性
- 觀察全部屬性
由于 express 創(chuàng)建 app, 混入了很多的屬性和方法所以需要對(duì)其進(jìn)行有基本的認(rèn)識(shí),其中被本文關(guān)注的 _router 是需要重點(diǎn)關(guān)注的
- _router對(duì)象
_router 對(duì)象屬性比較簡(jiǎn)單,其中需要關(guān)注的就是 stack 屬性,因?yàn)?stack 屬性后期會(huì)被遍歷取出 layer 來(lái)獲取 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 對(duì)象存儲(chǔ)的 Layer 實(shí)例,不是 route 對(duì)象的不添加 layer.route 為空:
以 query 內(nèi)置中間件為例, route 是 undefined,表示不是路由,反之。
- 手動(dòng)添加的路由 router 對(duì)象,保存了自己的 route 信息
- path
- stack
- methods
- ...
route 中保存了自己的 stack 屬性,stack 保存屬于本路由的 layer, 暫且稱之為 routeLayer, routeLayer 實(shí)例中保持了 handle 方法,這個(gè)方法就是我們?cè)?express 中寫的最多的路由處理函數(shù)。
分析 _router 的嵌套對(duì)象
_router 對(duì)象是 app 對(duì)象的屬性,是整個(gè)對(duì)象的路由屬性。
- _router.stack 存儲(chǔ)了所有的 RouterLayer 對(duì)象,stack 中 RouterLayer 有自己的添加順序,內(nèi)置 query/expressInit 中間件被首先添加,然后是手動(dòng)添加的路由和中間件。
- RouterLayer 中存在 route 屬性,純中間件 route 屬性為未定義,路由相關(guān)中間件 route 指向 Route 實(shí)例對(duì)象。app -> _router -> stack -> routerLayer[] -> routerLayer/routerLayer.route -> route.stack -> routeLayer[]/-> routeLayer/routeLayer.handle。
_router 對(duì)象的相關(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ù)中被實(shí)現(xiàn),并且是懶實(shí)現(xiàn)(有了就不在重新實(shí)現(xiàn)了),實(shí)現(xiàn)之后立即添加兩個(gè)中間件。本質(zhì)就是一個(gè) Router 類的實(shí)例。
_router 的數(shù)據(jù)結(jié)構(gòu)分析
- _router 不是頂層數(shù)據(jù),app 才是。
- _router 中保存了 router 相關(guān)的重要數(shù)據(jù)。stack 屬性中保存所有的 routerlayer 層級(jí)數(shù)據(jù)。
- _router.stack 的每一個(gè) layer 中 route 屬性一個(gè)有效路由數(shù)據(jù)。
- route 中也保存了 stack route 層的 layer 數(shù)據(jù)。
- route 層級(jí)的 layer 保存了 handle 和 handle 的參數(shù)
- _router 數(shù)據(jù)結(jié)構(gòu)中嵌套兩個(gè)棧一個(gè)是 router.stack 棧,一個(gè)是 route.stack 棧,保存自己層級(jí)的數(shù)據(jù)。
- handle 作為底層路由的處理函數(shù),被保存在 route.stack 的 layer 中
_router 中包含 router 和 route 層,每一層都自己的 stack, router 層與 route 層通過(guò) stack 的 layer 中的 route 屬性鏈接,route 與 handle 函數(shù)鏈接通過(guò) route 中 stack 儲(chǔ)存的 layer 的 handle 屬性鏈接,這就構(gòu)成一個(gè) _router 的數(shù)據(jù)結(jié)構(gòu):
小結(jié)
本文主要關(guān)注 _router 對(duì)象,以及其 vscode 調(diào)試方法,屬性層級(jí)和對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)。熟悉其內(nèi)部源碼實(shí)現(xiàn)。
以上就是Express框架中_router 對(duì)象數(shù)據(jù)結(jié)構(gòu)使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Express _router 對(duì)象數(shù)據(jù)結(jié)構(gòu)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js閉包所用的場(chǎng)合以及優(yōu)缺點(diǎn)分析
這篇文章主要介紹了js閉包所用的場(chǎng)合以及優(yōu)缺點(diǎn)分析,十分的詳細(xì)使用,有需要的小伙伴可以參考下。2015-06-06JavaScript實(shí)現(xiàn)簡(jiǎn)易的水印覆蓋功能
本文將簡(jiǎn)單實(shí)現(xiàn)一個(gè)覆蓋水印的小功能,水印一般都是添加在圖片上,然后直接加載處理過(guò)的圖片url即可,這里并沒(méi)有修改圖片,而是直接的在待添加水印的?dom?上添加一個(gè)?canvas?蒙版,需要的可以參考一下2022-12-12js getBoundingClientRect使用方法詳解
這篇文章主要介紹了js getBoundingClientRect使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07javascript實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼案例
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07JS驗(yàn)證逗號(hào)隔開(kāi)可以是中文字母數(shù)字
這篇文章主要介紹了JS驗(yàn)證逗號(hào)隔開(kāi)可以是中文字母數(shù)字 的相關(guān)資料,需要的朋友可以參考下2016-04-04JavaScript實(shí)現(xiàn)簡(jiǎn)單鐘表時(shí)鐘
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單鐘表時(shí)鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10動(dòng)態(tài)加載js、css的簡(jiǎn)單實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇?jiǎng)討B(tài)加載js、css的簡(jiǎn)單實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05