94 # express 兼容老的路由写法

news2024/12/23 9:55:41

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

看个 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) {
    // 产生 route
    let 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.coloradmin.cn/o/1041764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AIGC: 区块链与数据安全

随着国家将区块链纳入战略发展规划&#xff0c;数字经济蓬勃发展。近年来&#xff0c;数据的流通成为了实体经济赋能的关键&#xff0c;而在这一过程中&#xff0c;区块链技术和数据安全变得至关重要。 中国已经成为全球最大的数据体&#xff0c;每天产生大量数据。数字经济已…

Unity 协程(Coroutine)的原理以及用法

目录 事件函数的执行顺序定义使用yield instruction中的子类 总结 参考链接 &#xff1a;Unity 5分钟基础的了解协程 事件函数的执行顺序 定义 定义&#xff1a;开启一段和主程序异步执行的逻辑异步执行&#xff1a;是指语句在异步执行模式下&#xff0c;各语句执行结束的顺序…

Python异步编程之web框架 异步vs同步 文件IO任务压测对比

主题&#xff1a;比较异步框架和同步框架在文件IO操作的性能差异python版本&#xff1a;python 3.8压测工具&#xff1a;locustweb框架&#xff1a;同步&#xff1a;flask 异步&#xff1a;aiohttp、starlette异步文件模块&#xff1a;aiofiles、anyio.Path请求并发量: 模拟10个…

EPICS sequencer状态机示例

状态机源代码&#xff1a; #define PVSYS "pvsysca" #define LIGHT "{prefix}:light" #define LIGHTON "{prefix}:lightOn" #define LIGHTOFF "{prefix}:lightOff" #define VOLTAGE "{prefix}:voltage" #define LO…

机器人过程自动化(RPA)入门 3. 顺序、流程图和控制流程

到目前为止&#xff0c;我们已经了解了RPA是什么&#xff0c;并且我们已经看到了通过记录任务的活动并运行它来训练UiPath机器人是多么简单。使用记录器的UiPath可以很容易地自动化日常任务。在我们开始自动化复杂的任务之前&#xff0c;让我们学习如何控制从一个到另一个的活动…

【算法分析与设计】算法概述

目录 一、学习要点二、算法的定义三、算法的性质四、程序(Program)五、问题求解(Problem Solving)六、算法的描述七、算法分析的目的八、算法复杂性分析&#xff08;一&#xff09;算法时间复杂性分析&#xff08;二&#xff09;算法渐近复杂性1、渐进上界记号-大O符号2、渐进下…

Prometheus+Grafana监控K8S集群(基于K8S环境部署)

文章目录 一、环境信息二、部署前准备工作三、部署Prometheus监控系统四、部署Node_exporter组件五、部署Kube_state_metrics组件六、部署Grafana可视化平台七、Grafana可视化显示Prometheus收集数据八、Grafana添加监控模板九、拓展 一、环境信息 1、服务器及K8S版本信息&…

现代卷积网络实战系列4:PyTorch从零构建VGGNet训练MNIST数据集

&#x1f308;&#x1f308;&#x1f308;现代卷积网络实战系列 总目录 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 1、MNIST数据集处理、加载、网络初始化、测试函数 2、训练函数、PyTorch构建LeNet网络 3、PyTorch从零构建AlexNet训练MNIST数据…

【7.Vue 利用Heatmap.js 制作自定义热力图】

1.效果 2.背景 需要根据后端检测的设备的数值显示设备周围的清洁度,用户希望用热力图的方式来显示,于是在网上找了资料,发现可以用Heatmap.js来实现。 Heatmap.js 官网:https://www.patrick-wied.at/static/heatmapjs/ 3.引入组件 安装Heatmap.js npm install Heatmap.…

京东(JD)——利用人工智能实现自动零售

京东(JD)是中国最大的在线零售商之一&#xff0c;也是一家以高科技和人工智能物流而闻名的公司&#xff0c;其人工智能物流系统包括无人机交付系统、自动配送快递车以及机器人自动化配送中心。 京东一直致力于将机器人用于尽可能多地实现零售业务的物理自动化。 1.京东的人工智…

Nginx WEB访问与Linux授权约束

看到所有文件的权限都是没有的&#xff0c;即便所有的权限都没有即使nginx做了配置&#xff0c;这些都是正确的。那么在浏览器真正去访问的时候是不能访问的。 [rootjenkins html]# ls -l total 4 drwxr-xr-x 2 root root 23 Sep 16 17:43 dist ---------- 1 root root 33 Sep …

解决百度网盘登录安全验证显示空白页

百度网盘Windows客户端第一次登陆时会让验证身份 不知道什么BUG&#xff0c;有的系统能直接验证&#xff0c;有的系统不能&#xff0c;对于我这种频繁换环境的是真的难受。 试过网上各种方法&#xff0c;什么重启、重装、在IE设置中添加信任站点、清除IE缓存都不行。 但是这些…

nodejs+vue 医院病历管理系统

系统使用权限分别包括管理员、病人和医生&#xff0c;其中管理员拥有着最大的权限&#xff0c;同时管理员的功能模块也是最多的&#xff0c;管理员可以对系统上所有信息进行管理。用户可以修改个人信息&#xff0c;对医院病历信息进行查询&#xff0c;对住院信息进行添加、修改…

手机资讯:华为Mate60 Pro上手体验三天的使用体验

最近华为Mate60 Pro开售的消息引爆了整个数码科技圈&#xff0c;毕竟还没开发布会就直接开售新机&#xff0c;这放在整个手机界都是绝无仅有的&#xff0c;并且华为也官方放出了华为Mate60系列的所有参数配置&#xff0c;但唯独没有公开芯片型号和网络信号类型&#xff0c;不免…

ICCV 2023|Occ2Net,一种基于3D 占据估计的有效且稳健的带有遮挡区域的图像匹配方法...

本文为大家介绍一篇入选ICCV 2023的论文&#xff0c;《Occ2Net: Robust Image Matching Based on 3D Occupancy Estimation for Occluded Regions》&#xff0c; 一种基于3D 占据估计的有效且稳健的带有遮挡区域的图像匹配方法。 论文链接&#xff1a;https://arxiv.org/abs/23…

SQLyog安装教程

安装完MySQL数据库之后&#xff0c;为了便于我们对数据库的操作&#xff0c;所以安装一个用于数据库可视化的软件SQLyog。以下是安装步骤&#xff1a; 1. 解压之后安装。 选择SQLyog.exe或者SQLyog-11.2.4-0.X86。打开安装包之后&#xff0c;需要改安装路径的该安装路径&…

智慧公厕数字技术实现城市公共厕所智能升级

随着城市化进程的不断加快&#xff0c;城市公共厕所作为一个重要的基础设施&#xff0c;扮演着不可忽视的角色。然而&#xff0c;在现实中&#xff0c;很多城市公共厕所的设施陈旧、管理不善&#xff0c;给人们的生活带来了许多不便。为了解决这一问题&#xff0c;智慧公厕数字…

节省草稿纸的方法

问题描述&#xff1a;平时需要写一些简单的算法&#xff0c;手边没有草稿纸怎么办&#xff1f; 问题解决&#xff1a;可以使用一个QQ截图或者其他截图&#xff0c;然后使用画笔在截图上进行简单写画。在进行网上授课时&#xff0c;也可以常用这种方法。 如下图所示&#xff1…

PriorityQueue如何确定构建的是大根堆还是小根堆

PriorityQueue可以自定义传入的Comparator来比较内部元素的大小&#xff0c;Comparator比较时的返回如下&#xff1a; 如果o1 o2 ,返回0 如果o1 < o2 ,即 o1-o2 < 0 ,则返回负数 如果o1 > o2 ,即 o1-o2 > 0 ,则返回正数 如下是PriorityQueue类中新放入元素时执行的…

数据一致性:核心概念与实现策略

在当今的信息时代&#xff0c;数据已经成为了企业的核心资产之一。然而&#xff0c;随着数据量的不断增长和应用场景的不断扩大&#xff0c;如何保证数据的一致性成为了一个重要的挑战。数据一致性不仅关系到系统的正确性和可靠性&#xff0c;也直接影响到用户的体验和企业的业…