Делить переменные между файлами в Node.js?
Вот 2 файла:
// main.js
require('./modules');
console.log(name); // prints "foobar"
// module.js
name = "foobar";
Когда у меня нет "вар", это работает. Но когда у меня есть:
// module.js
var name = "foobar";
имя будет не определено в main.js.
Я слышал, что глобальные переменные плохие, и вам лучше использовать "var" перед ссылками. Но так ли это, когда глобальные переменные хороши?
8 ответов
Глобальные переменные почти никогда не бывают полезными (может быть, исключение или два там...). В этом случае, похоже, вы действительно хотите экспортировать свою переменную "name". Например,
// 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;
Я не могу найти сценарий, где глобальный 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 (как я когда-то недавно) попытался организовать способ обработки данных там, потому что это может действительно запутаться быстрый.
Если нам нужно совместно использовать несколько переменных, используйте следующий формат
//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'
Обновить
Сохраните любую переменную, которую хотите использовать как один объект. Затем передайте его загруженному модулю, чтобы он мог обращаться к переменной через ссылку на объект.
// myModule.js
var shared = null;
function init(obj){
shared = obj;
}
module.exports = {
init:init
}
,
// main.js
var myModule = require('./myModule.js');
var shares = {value:123};
myModule.init(shares);
Старый ответ
Чтобы разделить переменную между модулями, вы можете использовать функцию, чтобы получить значение переменной между основным и модулями.
//myModule.js
var mainFunction = null; //You can also put function reference in a Object or Array
function functionProxy(func){
mainFunction = func; //Save the function reference
}
// --- Usage ---
// setTimeout(function(){
// console.log(mainFunction('myString'));
// console.log(mainFunction('myNumber'));
// }, 3000);
module.exports = {
functionProxy:functionProxy
}
,
//main.js
var myModule = require('./myModule.js');
var myString = "heyy";
var myNumber = 12345;
function internalVariable(select){
if(select=='myString') return myString;
else if(select=='myNumber') return myNumber;
else return null;
}
myModule.functionProxy(internalVariable);
// --- If you like to be able to set the variable too ---
// function internalVariable(select, set){
// if(select=='myString'){
// if(set!=undefined) myString = set;
// else return myString;
// }
// else if(select=='myNumber'){
// if(set!=undefined) myNumber = set;
// else return myNumber;
// }
// else return null;
// }
Вы всегда можете получить значение от main.js
даже значение было изменено..
Переменная, объявленная с ключевым словом var или без него, была присоединена к глобальному объекту. Это основа для создания глобальных переменных в Node путем объявления переменных без ключевого слова var. В то время как переменные, объявленные с ключевым словом var, остаются локальными для модуля.
см. эту статью для дальнейшего понимания - https://www.hacksparrow.com/global-variables-in-node-js.html
Не новый подход, но немного оптимизированный. Создайте файл с глобальными переменными и поделитесь ими
export
и
require
. В этом примере Getter и Setter являются более динамичными, и глобальные переменные могут быть доступны только для чтения. Чтобы определить больше глобальных объектов, просто добавьте их в
globals
объект.
global.js
const globals = {
myGlobal: {
value: 'can be anytype: String, Array, Object, ...'
},
aReadonlyGlobal: {
value: 'this value is readonly',
protected: true
},
dbConnection: {
value: 'mongoClient.db("database")'
},
myHelperFunction: {
value: function() { console.log('do help') }
},
}
exports.get = function(global) {
// return variable or false if not exists
return globals[global] && globals[global].value ? globals[global].value : false;
};
exports.set = function(global, value) {
// exists and is protected: return false
if (globals[global] && globals[global].protected && globals[global].protected === true)
return false;
// set global and return true
globals[global] = { value: value };
return true;
};
примеры для получения и установки в any-other-file.js
const globals = require('./globals');
console.log(globals.get('myGlobal'));
// output: can be anytype: String, Array, Object, ...
globals.get('myHelperFunction')();
// output: do help
let myHelperFunction = globals.get('myHelperFunction');
myHelperFunction();
// output: do help
console.log(globals.set('myGlobal', 'my new value'));
// output: true
console.log(globals.get('myGlobal'));
// output: my new value
console.log(globals.set('aReadonlyGlobal', 'this shall not work'));
// output: false
console.log(globals.get('aReadonlyGlobal'));
// output: this value is readonly
console.log(globals.get('notExistingGlobal'));
// output: false
С другим мнением, я думаю, global
переменные могут быть лучшим выбором, если вы собираетесь опубликовать свой код в npm
Потому что вы не можете быть уверены, что все пакеты используют один и тот же выпуск вашего кода. Так что если вы используете файл для экспорта singleton
объект, это вызовет проблемы здесь.
Ты можешь выбрать global
, require.main
или любые другие объекты, которые являются общими для файлов.
Пожалуйста, скажите мне, если есть какие-то лучшие решения.
Если целью является браузер (путем связывания кода Node через Parcel.js или аналогичного), вы можете просто установить свойства наwindow
объект, и они становятся глобальными переменными:
window.variableToMakeGlobal = value;
Затем вы можете получить доступ к этой переменной из всех модулей (и вообще из любого контекста Javascript).