94 # express 兼容老的路由写法

上一节实现了错误处理中间件,这一节来实现兼容老的路由写法

看个 express 的二级路由的例子

const express = require("express");
const userRouter = require("./routes/userRouter");
const articleRouter = require("./routes/articleRouter");
const app = express();// 对用户进行操作,对文章进行操作app.use("/user", userRouter);
app.use("/article", articleRouter);app.listen(3000, () => {console.log(`server start 3000`);console.log(`在线访问地址:http://localhost:3000/`);
});

/routes/userRouter.js

const express = require("express");let router = express.Router(); // 是个构造函数router.get("/add", function (req, res) {res.end("/user-add");
});
router.get("/remove", function (req, res) {res.end("/user-remove");
});module.exports = router;

/routes/articleRouter.js

const express = require("express");let router = express.Router(); // 是个构造函数router.get("/add", function (req, res) {res.end("/article-add");
});
router.get("/remove", function (req, res) {res.end("/article-remove");
});module.exports = router;

在这里插入图片描述

上面的核心方法就是 express.Router(),下面来实现该方法

new 特点:当 new 一个函数时,这个函数返回一个引用类型,那么这个引用类型会作为 this

express.js 里添加 Router

const Application = require("./application");function createApplication() {// 通过类来实现分离操作return new Application();
}// 提供一个 Router 类,这个类可以 new 也可以当做函数来执行
createApplication.Router = require("./router");module.exports = createApplication;

然后声明一个 proto 对象,通过让路由的实例可以通过链找到原来的方法就能兼容老的路由写法

const url = require("url");
const Route = require("./route");
const Layer = require("./layer");
const methods = require("methods");function Router() {// 创建路由系统let router = (req, res, next) => {// 二级路由res.end("req.url----->" + req.url);};// 兼容老的路由写法// 维护所有的路由router.stack = [];// router 链上得有 get 等方法// 让路由的实例可以通过链找到原来的方法router.__proto__ = proto;return router;
}let proto = {};proto.route = function (path) {// 产生 routelet route = new Route();// 产生 layer 让 layer 跟 route 进行关联let layer = new Layer(path, route.dispatch.bind(route));// 每个路由都具备一个 route 属性,稍后路径匹配到后会调用 route 中的每一层layer.route = route;// 把 layer 放到路由的栈中this.stack.push(layer);return route;
};methods.forEach((method) => {proto[method] = function (path, ...handlers) {// 1.用户调用 method 时,需要保存成一个 layer 当道栈中// 2.产生一个 Route 实例和当前的 layer 创造关系// 3.要将 route 的 dispatch 方法存到 layer 上let route = this.route(path);// 让 route 记录用户传入的 handler 并且标记这个 handler 是什么方法route[method](handlers);};
});proto.use = function (path, ...handlers) {// 默认第一个是路径,后面是一个个的方法,路径可以不传if (typeof path === "function") {handlers.unshift(path);path = "/";}// 如果是多个函数需要循环添加层for (let i = 0; i < handlers.length; i++) {let layer = new Layer(path, handlers[i]);// 中间件不需要 route 属性layer.route = undefined;this.stack.push(layer);}
};proto.handle = function (req, res, out) {console.log("请求到了");// 需要取出路由系统中 Router 存放的 layer 依次执行const { pathname } = url.parse(req.url);let idx = 0;let next = (err) => {// 遍历完后没有找到就直接走出路由系统if (idx >= this.stack.length) return out();let layer = this.stack[idx++];if (err) {console.log("统一对中间件跟路由错误处理");// 找错误处理中间件if (!layer.route) {// 如果是中间件自己处理layer.handle_error(err, req, res, next);} else {// 路由则跳过,继续携带错误向下执行next(err);}} else {// 需要判断 layer 上的 path 和当前请求路由是否一致,一致就执行 dispatch 方法if (layer.match(pathname)) {// 中间件没有方法可以匹配,不能是错误处理中间件if (!layer.route) {if (layer.handler.length !== 4) {layer.handle_request(req, res, next);} else {next();}} else {// 将遍历路由系统中下一层的方法传入// 加速匹配,如果用户注册过这个类型的方法在去执行if (layer.route.methods[req.method.toLowerCase()]) {layer.handle_request(req, res, next);} else {next();}}} else {next();}}};next();
};module.exports = Router;

测试demo如下

const express = require("./kaimo-express");
const userRouter = require("./routes2/userRouter");
const articleRouter = require("./routes2/articleRouter");
const app = express();// 对用户进行操作,对文章进行操作app.use("/user", userRouter);
app.use("/article", articleRouter);app.use("/", (req, res, next) => {res.end("kaimo");
});app.listen(3000, () => {console.log(`server start 3000`);console.log(`在线访问地址:http://localhost:3000/`);
});

另外两个文件改成 引用自己实现的 express 即可

const express = require("../kaimo-express");

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/141515.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫技术系列-02HTML解析-xpath与lxml

Python爬虫技术系列-02HTML解析-xpath与lxml 2 XPath介绍与lxml库2.1 XPath概述2.2 lxml库介绍2.2.1 lxml库安装2.2.2 lxml库基本使用2.2.3 lxml案例a.读取数据并补全b.读取数据并选取节点&#xff1a; 2 XPath介绍与lxml库 参考连接&#xff1a; XPath教程 https://www.w3sch…

高效管理生活:Microsoft To Do for Mac 微软待办事项软件

在日常生活中&#xff0c;我们经常面临着琐碎的任务和繁忙的安排。为了更好地管理自己的时间和事务&#xff0c;一款强大而智能的待办事项软件是必不可少的。Microsoft To Do for Mac 微软待办事项软件将助您高效管理生活&#xff0c;让每件事都尽在掌握。 Microsoft To Do fo…

腾讯mini项目-【指标监控服务重构-会议记录】2023-07-26

2023-07-26组长会议纪要 A组 项目对齐和问题 分配需求&#xff0c;SLI指标上报&#xff0c;暂时没有实际效果 每个人负责一条指标&#xff0c;同步代码&#xff0c;时间问题还是难题跟B组同学请教&#xff0c;答疑 问题&#xff1a;启动 Tracer 【已解决】 环境问题&#xf…

数据结构:堆的简单介绍

目录 堆的介绍:(PriorityQueue) 大根堆:根节点比左右孩子节点大 小根堆:根节点比左右孩子节点小 堆的存储结构: 为什么二叉树在逻辑上用满二叉树结构,而不是普通二叉树呢? 因为如果是普通二叉树会造成资源的浪费​编辑 堆的介绍:(PriorityQueue) 堆又称优先级队列,何为优先…

uni-app使用HBuilder X编辑器本地打包apk步骤说明

1.下载安装Android Studio 下载地址官方地址&#xff1a;Android Studio 下载文件归档 | Android 开发者 | Android Developers 安装Android SDK和Google USB Driver即可&#xff0c;后者主要是为了后期使用USB设置的&#xff0c;如果不需要可以不点。 2.下载uni-app提供…

ElementUI之登陆+注册->饿了吗完成用户登录界面搭建,axios之get请求,axios之post请求,跨域,注册界面

饿了吗完成用户注册登录界面搭建axios之get请求axios之post请求跨域注册界面 1.饿了吗完成用户注册登录界面搭建 将端口号8080改为8081 导入依赖&#xff0c;在项目根目录使用命令npm install element-ui -S&#xff0c;添加Element-UI模块 -g&#xff1a;将依赖下载node_glod…

大数据flink篇之一-基础知识

一、起源 2010至2014年间&#xff0c;由柏林工业大学、柏林洪堡大学和哈索普拉特纳研究所联合发起名Stratosphere的研究项目。2014年4月&#xff0c;项目贡献给Apache基金会&#xff0c;成为孵化项目。更名为Flink2014年12月&#xff0c;成为基金会顶级项目2015年9月&#xff…

02 MIT线性代数-矩阵消元 Elimination with matrices

一, 消元法 Method of Elimination 消元法是计算机软件求解线形方程组所用的最常见的方法。任何情况下&#xff0c;只要是矩阵A可逆&#xff0c;均可以通过消元法求得Axb的解 eg: 我们将矩阵左上角的1称之为“主元一”&#xff08;the first pivot&#xff09;&#xff0c;第…

算法-贪心+优先级队列-IPO

算法-贪心优先级队列-IPO 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/ipo/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 回溯法 2.1 思路 2.2 代码 class Solution {int result 0;public int findMaximizedCapital(int …

【C语言】进阶——结构体+枚举+联合

①前言&#xff1a; 在之前【C语言】初阶——结构体 &#xff0c;简单介绍了结构体。而C语言中结构体的内容还有更深层次的内容。 一.结构体 结构体(struct)是由一系列具有相同类型或不同类型的数据项构成的数据集合&#xff0c;这些数据项称为结构体的成员。 1.结构体的声明 …

[LLM+AIGC] 01.应用篇之中文ChatGPT初探及利用ChatGPT润色论文对比浅析(文心一言 | 讯飞星火)

近年来&#xff0c;人工智能技术火热发展&#xff0c;尤其是OpenAI在2022年11月30日发布ChatGPT聊天机器人程序&#xff0c;其使用了Transformer神经网络架构&#xff08;GPT-3.5&#xff09;&#xff0c;能够基于在预训练阶段所见的模式、统计规律和知识来生成回答&#xff0c…

pytest之parametrize()实现数据驱动

第一个参数是字符串&#xff0c;多个参数中间用逗号隔开 第二个参数是list,多组数据用元组类型;传三个或更多参数也是这样传。list的每个元素都是一个元组&#xff0c;元组里的每个元素和按参数顺序一一对应 传一个参数 pytest.mark.parametrize(‘参数名’&#xff0c;list)…

CMU15-213 课程笔记 04-Floating Point

文章目录 浮点数如何用二进制表示IEEE 浮点数标准IEEE 浮点数实现IEEE 浮点数在内存里 E exp - bias 计算指数M 1.xxx 尾数计算举例&#xff1a;对一个浮点数进行转换一些关于浮点数的计算等等 浮点数如何用二进制表示 计算机内部的浮点数不是这样存在内存里的&#xff08;至…

【RabbitMQ实战】05 RabbitMQ后台管理

一、多租户与权限 1.1 vhost的概念 每一个 RabbitMQ服务器都能创建虚拟的消息服务器&#xff0c;我们称之为虚拟主机(virtual host),简称为 vhost。每一个 vhost本质上是一个独立的小型RabbitMQ服务器&#xff0c;拥有自己独立的队列、交换器及绑定关系等&#xff0c;并且它拥…

知识储备--基础算法篇-贪心算法

1.贪心算法 1.1贪心算法与背包问题的区别 贪心算法能够通过局部最优去推出全局最优&#xff0c;而背包问题不行&#xff0c;需要用动态规划的方法来解决。 1.2套路 贪心算法没有套路&#xff01;&#xff01; 主要想清楚怎么得到该阶段的局部最优解&#xff0c;如何通过局…

spring的ThreadPoolTaskExecutor装饰器传递调用线程信息给线程池中的线程

概述 需求是想在线程池执行任务的时候&#xff0c;在开始前将调用线程的信息传到子线程中&#xff0c;在子线程完成后&#xff0c;再清除传入的数据。 下面使用了spring的ThreadPoolTaskExecutor来实现这个需求. ThreadPoolTaskExecutor 在jdk中使用的是ThreadPoolExecutor…

前端web常用的基础案例

html案例&#xff1a; <!DOCTYPE html> <html> <head><title>My Website</title> </head> <body><header><h1>Welcome to My Website</h1><nav><ul><li><a href"#">Home</a…

阿里云效自动构建python自动测试脚本

之前一直用的是jenkins自动构建自动化脚本&#xff0c;因为现在的公司统一在阿里云效的流水线上做代码的管理&#xff0c;构建&#xff0c;要求自动化测试也在上面自动构建&#xff0c;故而学习了一下。为自己做一个记录&#xff0c;也给有需要的朋友做一个参考。 1. 新建流水…

Mysql备份恢复、与日志管理

Mysql日志管理、备份与恢复 一、Mysql日志管理1.1、日志分类1.1.1、错误日志1.1.2 、通用查询日志1.1.3、 二进制日志1.1.4 、慢查询日志1.1.5 、配置日志 1.2、日志的查询 二、备份与恢复2.1、 数据备份的必要性2.2 、造成数据丢失的原因2.3、 数据库备份的分类2.3.1、 物理备…

python 正则表达式

一、特殊字符-需要转义 eg&#xff1a;转义符&#xff1a; 待匹配的字符串&#xff1a;lr的值&#xff0c;及下图中字符串lr[和字符串&#xff0c;之间的数据 正则写法&#xff1a; learning_rate re.findall(".*lr\[(.*?), *", content) 处理结果&#xff1a;…