Совместное использование и изменение переменной между несколькими файлами node.js

main.js

var count = 1;

// psuedocode
// if (words typed begins with @add)
require('./add.js');

// if (words typed begins with @remove)
require('./remove.js');

// if (words typed begins with @total)
require('./total.js');



module.exports.count = count;

total.js

var count = require('./main.js').count;
console.log(count);

add.js

var count = require('./main.js').count;
count += 10;
console.log(count);

remove.js

var count = require('./main.js').count;
count -= 10;
console.log(count);

console.log

 1
 11
 -9

Фон:

У меня есть приложение (irc bot), и я хочу добавить функцию, которую peeps может выполнять @add 1 или @remove 1. У меня есть main.js, который затем требует разные файлы в зависимости от указанных триггеров. Таким образом, add вызовет файл add.js, а затем потребуется ('main.js') и добавит 10 (10 для упрощения, он фактически проанализирует число и будет использовать это число). У меня проблема, когда кто-то идет и делает @remove. Он требует ('main.js') и вычитает 10 из 1, что приводит к -9. И выполнение @total вывело бы 1.

Я выполнил довольно хороший поиск для module.exports, и я не сталкивался с примером, подобным приведенному выше. Документы не содержат примеров, близких к тому, что я хочу сделать; и эти вопросы 1, 2 я понимаю - но они мне не нужны - поскольку я понимаю, что там говорится.

Вопрос:

Я хотел бы, чтобы @add и @remove манипулировали одной и той же переменной ( count), и чтобы @total возвращал общее количество с учетом @add и @removes. Я использую module.exports неправильно; или существует общий способ совместного использования переменных, когда один файл может изменять содержимое файла module.exports и возвращать результаты в файл main.js?

4 ответа

Решение

Ваша проблема в том, что когда вы делаете var count = require('./main.js').count;вы получите копию этого номера, а не ссылку. изменения count не меняет "источник".

Однако у вас должны быть функции экспорта файлов. Запрос файла запустит его только в первый раз, но после этого он кэшируется и не запускается повторно. см документы

Предложение № 1:

// main.js
var count = 1;
var add = require('./add.js');
count = add(count);

// add.js
module.exports = function add(count) {
    return count+10;
}

# 2:

var count = 1;
var add = function() {
    count += 10;
}
add();

№ 3: Лично я бы создал модуль счетчика (это единственный экземпляр, но вы легко можете сделать его "классом"):

// main.js
var counter = require('./counter.js');
counter.add();
console.log(counter.count);

// counter.js
var Counter = module.exports = {
    count: 1,
    add: function() {
        Counter.count += 10;
    },
    remove: function() {
        Counter.count += 10;
    }
}

Не уверен, что это новое или нет, но вы действительно можете делить переменные между файлами как таковые:

main.js

exports.main = {
    facebook: null
};

counter.js

var jamie = require('./main'); 
console.info(jamie); //{facebook: null}
jamie.main.facebook = false;
console.info(jamie); //{facebook: false}

anothercheck.js

var jamie = require('./main'); 
console.info(jamie); //{facebook: null} //values aren't updated when importing from the same file.
jamie.main.facebook = true;
console.info(jamie); //{facebook: true}

Теперь вы можете делиться между файлами.

Я знаю, что немного опоздал с ответом на этот вопрос, всего 7 лет!

Вы можете просто использовать глобальную переменную:

global.myVar = 'my-val';
console.log(myVar); // returns 'my-val'
// from here on it's accessable to all modules by just the variable name

использование-глобальных-переменных-в-узле-js

У меня та же проблема, что и у вас. Иногда мне хочется делить переменные между несколькими файлами, потому что я люблю модульный стиль, например. разделение контроллера, функции, моделей в разных папках / файлах в моем скрипте node.js, чтобы я мог легко управлять кодом.

Я не знаю, является ли это лучшим решением, но я надеюсь, что подойдет вашим потребностям.

Модели /data.js

// exports empty array
module.exports = [];

Контроллеры /somecontroller.js

var myVar = require('../models/data');
myVar.push({name: 'Alex', age: 20});
console.log(myVar);
//  [{ name: 'Alex', age: 20 }]

Контроллеры /anotherController.js

var myVar = require('../models/data');

console.log(myVar);
// This array has value set from somecontroller.js before...
//  [{ name: 'Alex', age: 20 }]

// Put new value to array
myVar.push({name: 'John', age: 17});
console.log(myVar);
// Value will be added to an array
//  [{ name: 'Alex', age: 20 }, { name: 'John', age: 17}]

Нет никакого способа поделиться ссылкой между разными файлами. Ты не должен быть.

У меня есть main.js, который затем требует разных файлов в зависимости от триггеров, которые говорят

Я не думаю, что это хорошая идея. Все требуемые заявления, которые вам когда-либо понадобятся, должны быть в верхней части файла.

Я также вижу, что вы требуете main.js в total.js а также total.js в main.js, require() функция импортирует module.exports файла и присваивает его пространству имен, которое вы предоставляете. Ваш код не должен быть разбит на файлы таким образом. Вы извлекаете код в отдельные файлы только тогда, когда они сами являются модулями. И если вы это сделаете, вы не будете импортировать 2 файла друг на друга.

Также хорошо отметить, что в javascript, когда вы назначаете что-то пространству имен, оно копируется (клонируется), если это примитив. Если это объект, оба пространства имен ссылаются на один и тот же объект

var num = 5; 
var prim = num;
prim++; // prim is 6, but num is still 5.

var num = {five:5};
var ob  = num;
ob.five = 6;
console.log(num.five) //also 6.

Небольшой хак, который работает, но не рекомендуется, использует process переменная. Вы можете применить к нему различные свойства и, по существу, использовать их, как если бы window объект в браузере JS. Этот маленький хак даст ссылку на переменную. Это может быть изменено и изменено, и изменение будет перенесено на все файлы, которые requireд.

Но обратите внимание, что это не рекомендуется в качестве переопределения process Переменная может иметь неожиданные последствия и может привести к потере информации в случае вмешательства другого процесса.


file1.js:

const s1 = require('./file2');
process.num = 2;
console.log("file1", process.num);
s1.changeNum();
console.log("file1", process.num);

file2.js:

module.exports.changeNum = () => {
    process.num = 3;
    console.log("file2", process.num);
};

вывод:

file1 2

file2 3

file1 3

в качестве альтернативы всем остальным ответам

геттеры исеттеры

var _variableThing = 1223

module.exports = {
  get variableThing(){
    return _variableThing
  },

  set variableThing(val){
    _variableThing = val
  }
}

не будет работать с прямым импортом

Другие вопросы по тегам