如何在Express 4.17.1中动态获取当前中间件函数名称?
在Express ^4.17.1中动态获取中间件函数名称的解决方案
方法1:直接利用函数的name属性(最简方案)
每个命名函数都自带name属性,你可以在中间件内部直接引用函数自身的name属性,避免硬编码字符串。如果后续修改函数名,这个值会自动更新:
const path = require("path"); const currFile = path.basename(__filename); // 先将函数赋值给变量,方便内部引用 const getStudentAssets = function(req, res, next) { const { studentName } = req.body; if (typeof studentName !== "string") { // 直接获取函数的name属性 const middlewareName = getStudentAssets.name; const error = { status: 400, log: `ERROR on route ${req.originalUrl} in ${currFile} ${middlewareName} middleware`, }; return next(error); } // 业务逻辑处理 }; module.exports = { getStudentAssets };
注意:如果使用箭头函数,
name属性会为空字符串(匿名),所以必须使用命名普通函数(函数声明或命名函数表达式)。
方法2:通过req.route.stack匹配当前中间件
你可以遍历req.route.stack中的Layer对象,找到与当前执行的中间件函数匹配的项,从而获取其name属性。这种方法适合不想依赖函数变量引用的场景:
const path = require("path"); const currFile = path.basename(__filename); module.exports = { getStudentAssets(req, res, next) { const { studentName } = req.body; if (typeof studentName !== "string") { // 遍历栈找到当前中间件对应的Layer const currentLayer = req.route.stack.find(layer => layer.handle === arguments.callee); const middlewareName = currentLayer?.name; const error = { status: 400, log: `ERROR on route ${req.originalUrl} in ${currFile} ${middlewareName} middleware`, }; return next(error); } // 业务逻辑处理 }, };
注意:
arguments.callee在ES5严格模式下会被禁用,如果你的项目开启了严格模式,请改用方法1或方法3。
方法3:通用中间件包装器(批量处理)
如果你有大量中间件需要统一处理,可以写一个包装函数,自动将中间件名称注入到req对象中,避免重复代码:
第一步:编写包装函数
// middlewareWrapper.js function wrapMiddleware(middleware) { return function(req, res, next) { // 将中间件名称挂载到req上 req.currentMiddlewareName = middleware.name; return middleware(req, res, next); }; } module.exports = wrapMiddleware;
第二步:使用包装后的中间件
// 路由文件中 const wrapMiddleware = require('./middlewareWrapper'); const studentMiddleware = require('./studentMiddleware'); router.get('/student/assets', wrapMiddleware(studentMiddleware.getStudentAssets));
第三步:在中间件中直接使用
// studentMiddleware.js const path = require("path"); const currFile = path.basename(__filename); module.exports = { getStudentAssets(req, res, next) { const { studentName } = req.body; if (typeof studentName !== "string") { // 直接从req上获取注入的中间件名称 const error = { status: 400, log: `ERROR on route ${req.originalUrl} in ${currFile} ${req.currentMiddlewareName} middleware`, }; return next(error); } // 业务逻辑处理 }, };
这个方案的优势是一次配置,所有中间件都能复用,完全解耦名称获取逻辑和业务逻辑。
内容的提问来源于stack exchange,提问作者Kirk
相关产品推荐
相关产品推荐

