Поділитися змінними між файлами в Node.js?


126

Ось 2 файли:

// main.js
require('./modules');
console.log(name); // prints "foobar"

// module.js
name = "foobar";

Коли у мене немає "var", це працює. Але коли я маю:

// module.js
var name = "foobar";

ім'я не буде визначене в main.js.

Я чув, що глобальні змінні погані, і вам краще використовувати "var" перед посиланнями. Але це випадок, коли глобальні змінні є хорошими?

Відповіді:


184

Глобальні змінні майже ніколи не є хорошою справою (можливо, виняток чи два там ...). У такому випадку схоже, що ви просто хочете експортувати змінну "ім'я". Наприклад,

// module.js
var name = "foobar";
// export it
exports.name = name;

Потім у main.js ...

//main.js
// get a reference to your required module
var myModule = require('./module');

// name is a member of myModule due to the export above
var name = myModule.name;

1
глобальні змінні погані - я цілком згоден з цим. Але я міг би бути, що модуль має залежність від змінної. Чи є спосіб передати цю змінну в інший js-файл через функцію вимагати?
appsthatmatter

1
@ jjoe64 Не впевнений, я дотримуюся того, що ти маєш на увазі. Ви можете ефективно ділитися будь-яким значенням, яке ви хочете, через exportsоб’єкт.
jmar777

7
ОП запитує, чи можна визначити змінну в main.js, а потім використовувати її в module.js. У мене однакова вимога визначати шляхи, які використовуються знову і знову.
дизайнерська

4
@Designermonkey У такому випадку вам, мабуть, краще мати конфігураційний об’єкт із тими значеннями, які також можуть вимагати () 'd у заданому файлі. Зауважте, що ви можете просто робити, global.foo = 'bar'а потім отримувати доступ до fooбудь-якого місця, що вам захочеться ... але, як я вже сказав у своїй оригінальній відповіді, це майже ніколи не є хорошою справою.
jmar777

Дякую за це, я зрозумів, як це зробити, і це спрацює частування. Дякую за те, що перевірив, що я мав правильну ідею :)
дизайнер

37

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

Сценарій 1: Введіть матеріал у конфігураційні файли

Вам потрібно певне значення, яке воно однакове для програми, але воно змінюється залежно від середовища (виробництво, розробник або тест), типу повідомлень, наприклад, вам знадобиться:

// File: config/environments/production.json
{
    "mailerType": "SMTP",
    "mailerConfig": {
      "service": "Gmail",
      ....
}

і

// File: config/environments/test.json
{
    "mailerType": "Stub",
    "mailerConfig": {
      "error": false
    }
}

(зробіть аналогічну конфігурацію і для dev)

Щоб вирішити, який конфігурацію буде завантажено, створіть основний файл конфігурації (це буде використовуватися у всій програмі)

// File: config/config.js
var _ = require('underscore');

module.exports = _.extend(
    require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});

А тепер ви можете отримати такі дані :

// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));

Сценарій 2: Використовуйте файл констант

// File: constants.js
module.exports = {
  appName: 'My neat app',
  currentAPIVersion: 3
};

І використовувати це таким чином

// File: config/routes.js

var constants = require('../constants');

module.exports = function(app, passport, auth) {
  var apiroot = '/api/v' + constants.currentAPIVersion;
...
  app.post(apiroot + '/users', users.create);
...

Сценарій 3: Використовуйте допоміжну функцію для отримання / встановлення даних

Це не великий фанат цього, але, принаймні, ви можете відстежувати використання "імені" (посилаючись на приклад ОП) та встановлювати перевірки на місці.

// File: helpers/nameHelper.js

var _name = 'I shall not be null'

exports.getName = function() {
  return _name;
};

exports.setName = function(name) {
  //validate the name...
  _name = name;
};

І використовувати його

// File: controllers/users.js

var nameHelper = require('../helpers/nameHelper.js');

exports.create = function(req, res, next) {
  var user = new User();
  user.name = req.body.name || nameHelper.getName();
  ...

Можливо, може бути випадок використання, коли немає іншого рішення, ніж глобальне var, але зазвичай ви можете ділитися даними у вашому додатку, використовуючи один із цих сценаріїв, якщо ви починаєте використовувати node.js (як я колись тому), спробуйте організувати те, як ви обробляєте дані там, тому що вони можуть швидко заплутатися.


Мені сподобався сценарій 2, але чи можна змінити ці значення після того, як ми поговоримо про побудову? як найчастіше ми робимо, npm run build. Або ви знаєте якийсь спосіб змінити значення після побудови?
Кашиф Улла

@KashifUllah не впевнений, чи зможу я відповісти на ваш коментар лише за наданою інформацією, ви можете додати нове запитання на сайті
Felipe Pereira

16

Якщо нам потрібно поділити декілька змінних, скористайтеся наведеним нижче форматом

//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

Використання

  // main.js
    require('./modules');
    console.log(name); // print 'foobar'

2
лише коротка примітка, щоб залишити плутанину, яка може виникнути на першому місці: module.exports - це те, що слід використовувати! незалежно від того, як називається ваш js-файл (наприклад: global.js). Модуль - це об'єкт-вузол, який існує в глобальному масштабі! [так в глобальній.js ми використовуємо module.exports = .....]
Мохамед Аллал

він буде успішним, якщо ви видалите "нехай", і немає необхідності в "module.exports .."
Ахмад Захабі

6

Збережіть будь-яку змінну, яку потрібно поділити як один об'єкт. Потім передайте його завантаженому модулю, щоб він міг отримати доступ до змінної через посилання на об'єкт ..

// main.js
var myModule = require('./module.js');
var shares = {value:123};

// Initialize module and pass the shareable object
myModule.init(shares);

// The value was changed from init2 on the other file
console.log(shares.value); // 789

З іншого файлу ..

// module.js
var shared = null;

function init2(){
    console.log(shared.value); // 123
    shared.value = 789;
}

module.exports = {
    init:function(obj){
        // Save the shared object on current module
        shared = obj;

        // Call something outside
        init2();
    }
}

1

змінна, оголошена з або без ключового слова var, приєднана до глобального об'єкта. Це основа для створення глобальних змінних у Node шляхом оголошення змінних без ключового слова var. Хоча змінні, оголошені за допомогою ключового слова var, залишаються локальними для модуля.

Дивіться цю статтю для подальшого розуміння - https://www.hacksparrow.com/global-variables-in-node-js.html


3
Чи суперечать ці фрагменти? 1) "змінна, оголошена з або без ключового слова var, приєднана до глобального об'єкта." і 2) "змінні, оголошені за допомогою ключового слова var, залишаються локальними для модуля."
BaldEagle

1

З іншою думкою, я думаю, що globalзмінні можуть бути найкращим вибором, якщо ви збираєтесь опублікувати свій код npm, тому що ви не можете бути впевнені, що всі пакети використовують однаковий випуск вашого коду. Тож якщо ви використовуєте файл для експорту singletonоб’єкта, це спричинить тут проблеми.

Ви можете вибрати global, require.mainчи будь-які інші об'єкти , які є загальними для всіх файлів.

Скажіть, будь ласка, чи є якісь кращі рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.