Как передать параметр только промежуточному программному обеспечению, которому это нужно? - PullRequest
0 голосов
/ 02 июля 2018

У меня есть приложение Express, и я пытаюсь поместить все свое промежуточное ПО в отдельный файл. Некоторые функции промежуточного программного обеспечения нуждаются в объекте db, а некоторые нет.

Это довольно просто для функций, которым не нужен объект db, но, учитывая мою структуру кода ниже, как я могу ссылаться на объект 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()

middleware.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 ]

0 голосов
/ 09 июля 2018

Функциональный подход

Я думаю, что хорошей структурой для этого является попытка карри вашего промежуточного программного обеспечения. Это паттерн, применяемый промежуточным программным обеспечением, таким как 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 объекту один раз . Это устраняет необходимость повторного ввода 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 - это first , чтобы свойство было назначено перед его использованием:

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); 
0 голосов
/ 06 июля 2018

Почему бы просто не объявить 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 или какую-либо другую асинхронную библиотеку для включения после установки БД.

...