Совместное использование и изменение переменной между несколькими файлами 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
У меня та же проблема, что и у вас. Иногда мне хочется делить переменные между несколькими файлами, потому что я люблю модульный стиль, например. разделение контроллера, функции, моделей в разных папках / файлах в моем скрипте 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
}
}
не будет работать с прямым импортом