javascript - 如何仅将参数传递给需要它的中间件?
问题描述
我有一个 Express 应用程序,我正在尝试将所有中间件放在它自己的文件中。一些中间件函数需要该db
对象,而有些则不需要。
对于不需要db
对象的函数来说这很简单,但是鉴于下面的代码结构,我如何引用该db
对象,doesNotNeedDbParam
因为它已经有 params req
、res
和next
?
一些文件.js:
const router = express.Router()
const doesNotNeedDbParam = require('./middleware')().doesNotNeedDbParam
function foo () {
// Currently I have to call require and pass in the db object here b/c
// it's not set when requiring the function doesNotNeedDbParam
router.use(require('./middleware')(db).needsDbParam // <-- Is there a better way to do this so that I can require the file above and pass the db object in when it's set?
}
// Setup db object here
foo()
中间件.js
function doesNotNeedDbParam (req, res, next) {
...
}
function needsDbParam (req, res, next) {
// Where do I reference the db variable?
}
module.exports = (db) => {
return {
doesNotNeedDbParam: doesNotNeedDbParam,
needsDbParam: needsDbParam
}
}
解决方案
功能方法
我认为一个好的结构是尝试对你的中间件进行柯里化。这是中间件实践的一种模式,例如body-parser
Express 本身在内部使用serve-static
. 这样,您只需要求一次,然后通过db
您需要的地方,而不是您不需要的地方:
// Instead of declaring each function directly as a middleware function,
// we declare them as a function that returns a middleware function
function doesNotNeedDbParam () {
return function (req, res, next) {
…
}
}
function needsDbParam (db) {
return function (req, res, next) {
// You can use db here along with req, res, next
}
}
// No need to export a function now
module.exports = {
doesNotNeedDbParam,
needDbParam,
};
然后,只需要:
const middleware = require('./middleware');
…
router.use(middleware.doesNotNeedDbParam()); // Since this doesn't need anything, no argument
router.use(middleware.needsDbParam(db)); // You can pass db here now
如果您对 ES6+ 语法感到满意,您可以浓缩为:
const doesNotNeedDbParam = () => (req, res, next) => {
…
}
const needsDbParam = (db) => (req, res, next) => {
// Use db here
}
// Export object here...
然后:
const { doesNotNeedDbParam, needsDbParam } = require('./middleware');
…
router.use(doesNotNeedDbParam());
router.use(needsDbParam(db));
附加方法
还有另一种方法可以做到这一点,通过将属性附加到req
对象once。这消除了db
每次您想要它时都重新传递的需要。许多其他软件包使用此策略。它是这样的:
function attachDb (db) { // Still use curry approach here since we want db
return function (req, res, next) {
// Attaches the specified db to req directly
req.db = db;
}
}
function needsDbParam (req, res, next) { // No need for currying
// Now use req.db here
}
// Export your other middleware…
然后,像这样使用它,确保attachDb
首先在使用它之前分配属性:
router.use(attachDb(db)); // Before all other middleware that depend on req.db
…
// No need to call because this is already the middleware function,
// able to use req.db, which was assigned via attachDb
router.use(needDbParam);
推荐阅读
- javascript - 将 JS 事件侦听器添加到 Chrome 扩展弹出窗口
- mysql - 如何完成这个查询功能?
- arduino - 带有 Arduino Uno R3 开关控制的操纵杆将不显示开关按钮
- amazon-web-services - 在 Cognito 中查找用户名
- python - 在迭代 for 循环时出现生成器的问题
- airflow - 如果分支不收敛,气流能否在 dag 中运行分支任务?
- excel - 如何获得一个公式 5 年的每日结果并将它们放在一个表格中?
- c++ - openmp 并行中的 std::lock_guard
- javascript - 在从外部加载的 iframe 中进行更改
- python - 复选框值未在 tkinter 中更新