Передача аргументів на вимогу (при завантаженні модуля)


113

Чи можливо передавати аргументи під час завантаження модуля за допомогою вимагає?

У мене є модуль, login.js, який забезпечує функцію входу. Для цього потрібне підключення до бази даних, і я хочу, щоб те саме підключення до бази даних використовувалося у всіх моїх модулях. Тепер я експортую функцію login.setDatabase (...), яка дозволяє мені вказати підключення до бази даних, і це працює чудово. Але я б швидше передав базу даних та будь-які інші вимоги, коли завантажую модуль.

var db = ...
var login = require("./login.js")(db);

Я досить новий з NodeJS і зазвичай розвиваюсь за допомогою Java та Spring Framework, так що так ... це конструкторська інжекція :) Чи можливо зробити щось на зразок коду, який я подав вище?


Я також рекомендую переглянути відповіді на це питання. Як було зазначено у моїй відповіді, загальна ідіома полягає в тому, щоб передати appоб'єкт необхідним модулям.
Девід Уелдон

Замість того щоб робити все це міркування , що проходить по БД, ви могли б використовувати одноплідних реалізацію і викликати db.getInstance () , де це необхідно.
wulfgarpro

Відповіді:


236

На основі ваших коментарів у цій відповіді я роблю те, що ви намагаєтесь зробити так:

module.exports = function (app, db) {
    var module = {};

    module.auth = function (req, res) {
        // This will be available 'outside'.
        // Authy stuff that can be used outside...
    };

    // Other stuff...
    module.pickle = function(cucumber, herbs, vinegar) {
        // This will be available 'outside'.
        // Pickling stuff...
    };

    function jarThemPickles(pickle, jar) {
        // This will be NOT available 'outside'.
        // Pickling stuff...

        return pickleJar;
    };

    return module;
};

Я структурую майже всі мої модулі так. Здається, для мене це добре працює.


Чи потрібний appаргумент чи я можу його опустити? Мій модуль не використовує явного використання цього аргументу програми, але я не знаю, чи потрібен він node.js для якоїсь внутрішньої речі. Якщо це нормально, моя декларація модуля виглядатиме так:module.exports = function (db) {
Улісс Алвес

Це було специфічно для програми Express, тому точно не потрібно.
плаваючийЛомас

@floatingLomas Механізм сериализации в Python називається розсіл: stackoverflow.com/questions/11218477 / ...
SadSeven

1
Що ж станеться, якщо ви посилаєтеся на модуль кілька разів? Перший require(mymodule)(myargs)дасть вам модуль для роботи. Однак якщо ви посилаєтесь десь ще з іншого модуля ?? в базовій системі, здається, бере участь кеш, але в цій системі кеш повертає метод голого генератора при наступних дзвінках require(), і якби ви передали аргументи, require()(someargs)ви отримаєте інший модуль назад ... можливо, мені не вистачає щось
Том Н

2
@TomH У такому випадку ви хочете кешувати це. Для цього у вас буде var module;функція експорту, а потім, як тільки ви ввійдете в систему, ви хочете перевірити, чи moduleвона вже визначена, і якщо так, просто поверніть її (а якщо ні, ініціалізуйте її). Чи має це сенс?
плаваючий

37

Я не впевнений, чи все-таки це стане корисним людям, але за допомогою ES6 у мене є спосіб зробити це, що я вважаю чистим і корисним.

class MyClass { 
  constructor ( arg1, arg2, arg3 )
  myFunction1 () {...}
  myFunction2 () {...}
  myFunction3 () {...}
}

module.exports = ( arg1, arg2, arg3 ) => { return new MyClass( arg1,arg2,arg3 ) }

І тоді ви отримуєте очікувану поведінку.

var MyClass = require('/MyClass.js')( arg1, arg2, arg3 )

32

Так. У вашому loginмодулі просто експортуйте одну функцію, яка бере dbаргумент. Наприклад:

module.exports = function(db) {
  ...
};

1
Я спробував це. У login.js module.exports = function(app,db) { ... } module.exports.auth = function(req,res) { ... authentication stuff } він викликає функцію "анонімний" і встановлює appі dbзмінні, але, виконуючи це, моя програма не знайде authфункції. Що я роблю неправильно? Якщо я видалю анонімну функцію, authфункція знову стає доступною.
Андреас Селенволл

Як і все в JavaScript, exportsє об'єктом. Ви можете призначити йому властивості (багаторазовий експорт) або ви можете призначити їх за значенням. Це здається, що ви призначили експорт функції, але потім призначили auth як властивість функції, яку ви призначили експортувати. Тому вам потрібно буде зробити це, var auth = require("./login.js").authщо може бути не тим, що ви задумали. Якщо ви хочете використовувати шаблон із початкового питання, його, ймовірно, найкраще дотримуватися єдиного значення експорту. Якщо це все ще не має сенсу, я б рекомендував опублікувати суть для мене, щоб подивитися.
Девід Уелдон

1
Після повторного прочитання це здається, що ви, можливо, призначили authвластивість exportsоб'єкта, а потім пізніше в модулі, який ви призначили exportsфункції (тим самим переосмисливши попереднє призначення). Якщо ви скасуєте порядок призначення, ви зможете отримати доступ до authфункції, як ви очікували. Знову важко сказати, не бачивши код.
Девід Уелдон

1
Дякуємо багато за вашу допомогу. Те, що я не усвідомлював, було саме те, що ви прагнули з вимагати ("увійти"). Я , хоча не було ніякої різниці в var login = require('login')і var login = require('login')(app), але є величезна різниця, немає ніякої магії в анонімній функції повернулася, це просто ще одна функції / об'єкт. Замість того, щоб мати module.exports.auth, аномімна функція тепер повертає функцію auth (серед інших), тобто return { auth: authFunction, login: loginFunction}. Тож зараз це працює. Дякую.
Андреас Селенволл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.