Express框架中_router 对象数据结构使用详解

目录
  • _router 对象介绍
  • 使用调试直观的获取 _router 对象
  • 一个简单的可以运行的 demo
  • 使用 vscode 初始化一个调试文件
  • 在合适的地点打一个断点
  • 启动服务
  • 观察全部属性并找到 _router 对象以及属性
  • 找出 stack.layer 的排列顺序
  • 分析 _router 的嵌套对象
  • _router 对象的相关源码
  • _router 的数据结构分析
  • 小结

_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 调试方法,属性层级和对应数据结构。熟悉其内部源码实现。

以上就是Express框架中_router 对象数据结构使用详解的详细内容,更多关于Express _router 对象数据结构的资料请关注我们其它相关文章!

(0)

相关推荐

  • Express框架Router Route Layer对象使用示例详解

    目录 引言 Layer Route Router 方法统计 两个 stack 取出 stack 中 layer 从 Router 到 layer 的路径 Router.route 方法中的 dispatch next 函数 小结 引言 这使用倒叙的方式: 将 Layer 放在最前面讲解,然后是 Route 路由项目,最后是 Router 路由器. Layer Layer 是什么? Express 中最小的存储单元,存储的重要内容包括 handle 也就是 fn.path 等路径.fn 就是中间件

  • Express代理转发服务器实现

    目录 express的代理转发 项目结构 转发 转发记录 前端页面 express的代理转发 其实我的内心关于这个Express,我的内心是拒绝的,不是说,我对这个框架有什么看法,而是因为这个大作业的问题.是的我还是一个大三老菜鸡,苦练 Java 全干开发,Python 人工智能 整整 一坤年.期间拿了几个奖,水了篇论文 而已. 那么这篇文章主要做的,其实很简单就是,做个代理转发.前端请求,先到express服务器,然后转发到flask服务器,为什么非要转发呢,原因很简单,web作业非要用nod

  • Express框架req res对象使用详解

    目录 正文 IncomingMessage ServerResponse 请求对象 req 响应对象 设置状态码 如何来快速测试这些属性和方法呢? 下面给出一些示例代码 目录结构 安装依赖 小结 正文 Express 请求 req 和响应 res 对象定义: var req = Object.create(http.IncomingMessage.prototype) var res = Object.create(http.ServerResponse.prototype) 下面是属性继承关系

  • react express实现webssh demo解析

    目录 正文 实现 WebSSH 的基本思路 实现 Demo 的代码 服务器端代码 前端代码 在 React 应用中使用 WebSSH 组件 效果 总结 正文 下面是一个简单的 WebSSH Demo,实现了通过浏览器连接 SSH 服务器并进行交互的功能. 实现 WebSSH 的基本思路 WebSSH 可以分成以下几个模块: 前端界面:使用 xterm.js 实现一个基于浏览器的终端界面. WebSocket 连接:使用 WebSocket 连接连接 WebSSH 服务器后端. SSH 连接:使用

  • Express框架两个内置中间件方法详解

    目录 什么是中间件 两个内置的中间件 init 方法 query 中间件 被使用 小结 什么是中间件 中间件,就是具有串联执行能力的函数,Express中两种层面的中间件.app 层面的中间件, router 层面的中甲件.在 express 中, 一般通过 use 方法和路由的方法添加中间件. 两个内置的中间件 init 中间件方法 query 中间件方法 init 方法 exports.init = function(app){ return function expressInit(req

  • Python:Scrapy框架中Item Pipeline组件使用详解

    Item Pipeline简介 Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清晰.验证和存储数据. 当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数据. 每个Item管道的组件都是有一个简单的方法组成的Python类. 他们获取了Item并执行他们的方法,同时他们还需要确定的是是否需要在Item管道中继续执行下一步或是直接丢弃掉不处理. Item管道通常执行的过程有 清理HTML数据 验证解析到的数据(检查Item是否包含必要的字段) 检查是

  • JSP中out对象的实例详解

    JSP中out对象的实例详解 一 什么是缓冲区 缓冲区:Buffer,所谓缓冲区就是内存的一块区域用来保存临时数据. 二 out对象 out对象是JspWrite类的实例,是向浏览器输出内容常用的对象. 三 常用方法 四 实例 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> <% String path

  • YII框架中搜索分页jQuery写法详解

    控制层 use frontend\models\StudUser; use yii\data\Pagination; use yii\db\Query; /** * 查询 * */ public function actionSearch() { //接值 $where=Yii::$app->request->get(); //实例化query $query=new Query(); $query->from('stud_user'); //判断 if(isset($where['sex

  • Java中的对象和引用详解

    Java中的对象和引用详解 在Java中,有一组名词经常一起出现,它们就是"对象和对象引用",很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别和联系. 1.何谓对象? 在Java中有一句比较流行的话,叫做"万物皆对象",这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一段原话: "按照通俗的

  • Laravel框架中集成MongoDB和使用详解

    * 推荐组件 composer require jenssegers/mongodb ^3.3 -vvv(本人的laravel版本是5.5) 修改config/app.php * 注册服务 Jenssegers\Mongodb\MongodbServiceProvider::class, * 添加 Facades 'Mongo' => Jenssegers\Mongodb\MongodbServiceProvider::class, * 修改数据库配置文件 config/database.php

  • vue框架中props的typescript用法详解

    什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类型版本,除此之外,它还有一些扩展的语法,如interface/module等. typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript. Typescript 5年内的热度随时间变化的趋势,整体呈现一个上升的趋势.也说明ts越来越️受大家的关注了. 在vue中使用typescript时,需要引入vue-pro

  • AngularJS框架中的双向数据绑定机制详解【减少需要重复的开发代码量】

    本文实例讲述了AngularJS框架双向数据绑定机制.分享给大家供大家参考,具体如下: 之前写的一篇<AngularJS入门示例之Hello World详解> ,介绍ng-model的时候提到:使用AngularJS的双向数据绑定机制,不需要我们编写繁琐的代码来实现同样的功能.现在我们看一个比较震撼的例子,看看angularJS是如何减少我们在前端开发中的繁琐劳动的.越是感受到框架功能的强大,越是能够激发学习的兴趣和动力. 假如我们有一个学生信息列表,包含学生的姓名.地址和年龄信息.假如这个数

  • ES6中异步对象Promise用法详解

    本文实例讲述了ES6中异步对象Promise用法.分享给大家供大家参考,具体如下: 回忆一下ES5中的怎么使用异步方法 // es5中的异步回调 let ajax = function(callback){ console.log('执行') // 执行 setTimeout(() => { callback&&callback.call(); }, 1000) }; ajax(function(){ console.log('hello') // 1s后打印hello }); 使用

  • YII框架中使用memcache的方法详解

    本文实例讲述了YII框架中使用memcache的方法.分享给大家供大家参考,具体如下: yii中可以很方便的使用memcache 一.配置 在main.php的components中加入cache配置 array( 'components'=>array( 'cache'=>array( 'class'=>'CMemCache', 'servers'=>array( array( 'host'=>'server1', 'port'=>11211, 'weight'=&g

  • Spring Boot框架中的@Conditional注解示例详解

    目录 1. @Conditional 注解 2. Spring boot 扩展 1) @ConditionalOnClass和@ConditionalOnMissingClass注解 2) @ConditionalOnBean 和@ConditionalOnMissingBean注解 3) @ConditionalOnProperty注解 1. @Conditional 注解 @Conditional注解是Spring-context模块提供了一个注解,该注解的作用是可以根据一定的条件来使@Co

随机推荐