代码之家  ›  专栏  ›  技术社区  ›  Catfish

如何只将参数传递给需要它的中间件?

  •  1
  • Catfish  · 技术社区  · 7 年前

    我有一个Express应用程序,我正试图将我的所有中间件放在它自己的文件中。一些中间件功能需要 db 对象,有些则不然。

    对于不需要 分贝 对象,但考虑到下面的代码结构,如何引用 分贝 中的对象 doesNotNeedDbParam 因为它已经有参数了 req , res next ?

    somefile.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
      }
    }
    
    2 回复  |  直到 7 年前
        1
  •  8
  •   Andrew Li    7 年前

    功能性方法

    我认为一个好的结构是尝试 currying 你的中间件。这是由中间件(如 body-parser 内部通过表达自己 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 对象 一旦 . 这样就不需要重新打包 分贝 每次你想要的时候。许多其他软件包使用这种策略。就像这样:

    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); 
    
        2
  •  -1
  •   NoxelNyx    7 年前

    为什么不直接申报呢 module.exports 作为单一功能:

    module.exports = (db) => { 
        let module = {}; 
    
        module.doesNotNeedDbParam = (req, res) => {
            // Do Stuff
        };
    
        module.needsDbParam = (req, res) => { 
            // db now in scope
        };
    
        return module;
    };
    

    这就是你的 somefile.js 会变成:

    const router = express.Router();
    const db = initializeDb();
    
    const doesNotNeedDbParam = require('./middleware')().doesNotNeedDbParam;
    router.use(require('./middleware')(db).needsDbParam);
    

    您也可以这样设置它:

    const middleware = require('./middleware')(db);
    const doesNotNeedParam = middleware.doesNotNeedParam;
    router.use(middleware.needsDbParam);
    

    这与您以前所做的没有什么不同,但现在您可以访问 needsDbParam . 如果你的 initializeDb 函数是异步的,则需要使用 Promise 或者在数据库建立之后要包含的其他异步库。