Nodejs Express 有个 router.use(),有木有方法实现类似 router.unuse()来撤销router.use?
Nodejs Express 有个 router.use(),有木有方法实现类似 router.unuse()来撤销router.use?
在Express 4.x 中,通过router.use可以使用router级别的中间件,通过什么方式可以实现类似 router.unuse 的功能,来取消使用这个中间件。
这个过程都是在系统运行时进行的,答案不能是删掉相关代码重启应用哟。
在Express.js中,并没有直接提供router.unuse()
这样的方法来撤销已经注册的中间件。但是,我们可以通过一些技巧来实现类似的功能。下面是一个简单的示例代码,展示如何实现一个类似于router.unuse()
的功能。
示例代码
首先,我们需要创建一个自定义的方法来管理中间件的注册和撤销:
const express = require('express');
const app = express();
const router = express.Router();
// 存储已注册的中间件
const registeredMiddleware = [];
// 自定义的 use 方法
router.customUse = function (middleware) {
// 注册中间件
router.use(middleware);
// 记录已注册的中间件
registeredMiddleware.push(middleware);
};
// 自定义的 unuse 方法
router.customUnuse = function (middleware) {
// 查找并移除指定的中间件
const index = registeredMiddleware.indexOf(middleware);
if (index !== -1) {
// 移除已注册的中间件
registeredMiddleware.splice(index, 1);
// 移除路由上的中间件
router.stack = router.stack.filter(layer => layer.handle !== middleware);
}
};
// 示例中间件
const myMiddleware = (req, res, next) => {
console.log("Hello from myMiddleware");
next();
};
// 使用自定义的 customUse 方法注册中间件
router.customUse(myMiddleware);
// 使用自定义的 customUnuse 方法撤销中间件
router.customUnuse(myMiddleware);
app.use('/api', router);
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
-
自定义的
customUse
方法:- 这个方法与
router.use()
类似,但会将注册的中间件存储在一个数组中。
- 这个方法与
-
自定义的
customUnuse
方法:- 这个方法接受一个中间件作为参数,并从存储的数组中查找并移除它。
- 然后,它还会从
router.stack
中移除相应的中间件层。
通过这种方式,你可以在运行时动态地添加和移除中间件,而无需重启应用。这在某些需要动态配置的应用场景中非常有用。
刚略了下express的代码,有一个可行的办法:
遍历 router.stack
,找到router.stack[i].handle
=== 这个中间件的元素,删掉它就可以了。
不知道这样做有什么隐患,或者还有木有更好的方法。
proto.use = function(route, fn){ // default route to '/' if (‘string’ != typeof route) { fn = route; route = ‘/’; }
if (typeof fn !== ‘function’) { var type = {}.toString.call(fn); var msg = 'Router.use() requires callback functions but got a ’ + type; throw new Error(msg); }
// strip trailing slash if (’/’ == route[route.length - 1]) { route = route.slice(0, -1); }
var layer = new Layer(route, { sensitive: this.caseSensitive, strict: this.strict, end: false }, fn);
// add the middleware debug(‘use %s %s’, route || ‘/’, fn.name || ‘anonymous’);
this.stack.push(layer); return this; };
//this.stack.push(layer); 从router.stack 里面把LAYER删掉。可自写方法 EXPRESS/LIB/ROUTER/INDEX.JS
其实可以看一下源码,楼上也给出了,可以考虑自己发个merge request
当我执行 mysql.query(sql,callback); 的时候。。。
就很慢的刷新页面没有错误。。。但是在我不停的刷新页面的时候。。。。控制台就报错了。
错误提示如下图:
然后我去看了看 mysql错误提示的地方
不知道为什么。。。只要快速刷新页面, 过一会就报错一下。然后我express.send 也跟着报错。好像是在send设置响应头部的时候,已经有内容输出了。 但是 我 console.log(mysql err); 完全没错误任何东西。不是null 。
下面是全部错误。
在Express.js中,并没有内置的router.unuse()
方法来撤销已经添加的中间件。不过,你可以通过维护一个中间件列表的方式来实现类似的功能。
实现思路
- 创建一个自定义的路由器类。
- 使用一个数组来存储所有已添加的中间件。
- 提供一个方法来移除指定的中间件。
示例代码
const express = require('express');
class CustomRouter extends express.Router {
constructor(...args) {
super(...args);
this.middlewareList = [];
}
use(fn) {
super.use(fn);
this.middlewareList.push(fn);
}
unuse(fn) {
const index = this.middlewareList.indexOf(fn);
if (index !== -1) {
this.middlewareList.splice(index, 1);
// 重新创建路由,移除指定的中间件
const newRouter = express.Router();
this.stack.forEach(layer => {
if (!layer.handle._name.includes('anonymous')) { // 假设匿名函数不是我们需要移除的中间件
newRouter.use(layer.handle);
}
});
Object.assign(this, newRouter);
}
}
}
const app = express();
const customRouter = new CustomRouter();
customRouter.use((req, res, next) => {
console.log('This is a middleware');
next();
});
app.use('/api', customRouter);
// 使用unuse移除中间件
customRouter.unuse((req, res, next) => {
console.log('This is a middleware');
next();
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
- CustomRouter 类继承了
express.Router
类,并添加了一个middlewareList
数组来记录所有已添加的中间件。 use
方法不仅调用父类的use
方法添加中间件,还将中间件函数添加到middlewareList
数组中。unuse
方法遍历middlewareList
数组,找到并移除指定的中间件。- 在移除中间件后,我们重新创建一个新的
Router
实例,并将未被移除的中间件添加到新实例中,然后替换当前实例。
这种方法虽然能实现所需的功能,但可能会影响性能,特别是在中间件数量较多的情况下。因此,在实际应用中,应谨慎使用。