Share variables between files in Node.js?
Solution 1
Global variables are almost never a good thing (maybe an exception or two out there...). In this case, it looks like you really just want to export your "name" variable. E.g.,
// module.js
var name = "foobar";
// export it
exports.name = name;
Then, in 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;
Solution 2
I'm unable to find an scenario where a global var
is the best option, of course you can have one, but take a look at these examples and you may find a better way to accomplish the same:
Scenario 1: Put the stuff in config files
You need some value that it's the same across the application, but it changes depending on the environment (production, dev or test), the mailer type as example, you'd need:
// File: config/environments/production.json
{
"mailerType": "SMTP",
"mailerConfig": {
"service": "Gmail",
....
}
and
// File: config/environments/test.json
{
"mailerType": "Stub",
"mailerConfig": {
"error": false
}
}
(make a similar config for dev too)
To decide which config will be loaded make a main config file (this will be used all over the application)
// File: config/config.js
var _ = require('underscore');
module.exports = _.extend(
require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});
And now you can get the data like this:
// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));
Scenario 2: Use a constants file
// File: constants.js
module.exports = {
appName: 'My neat app',
currentAPIVersion: 3
};
And use it this way
// 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);
...
Scenario 3: Use a helper function to get/set the data
Not a big fan of this one, but at least you can track the use of the 'name' (citing the OP's example) and put validations in place.
// 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;
};
And use it
// 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();
...
There could be a use case when there is no other solution than having a global var
, but usually you can share the data in your app using one of these scenarios, if you are starting to use node.js (as I was sometime ago) try to organize the way you handle the data over there because it can get messy really quick.
Solution 3
If we need to share multiple variables use the below format
//module.js
let name='foobar';
let city='xyz';
let company='companyName';
module.exports={
name,
city,
company
}
Usage
// main.js
require('./modules');
console.log(name); // print 'foobar'
Solution 4
Save any variable that want to be shared as one object. Then pass it to loaded module so it could access the variable through object reference..
// 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
On the other file..
// 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();
}
}
Solution 5
Not a new approach but a bit optimized. Create a file with global variables and share them by export
and require
. In this example, Getter and Setter are more dynamic and global variables can be readonly. To define more globals, just add them to globals
object.
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;
};
examples to get and set in 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
Related videos on Youtube
never_had_a_name
Updated on August 18, 2021Comments
-
never_had_a_name almost 3 years
Here are 2 files:
// main.js require('./modules'); console.log(name); // prints "foobar" // module.js name = "foobar";
When I don't have "var" it works. But when I have:
// module.js var name = "foobar";
name will be undefined in main.js.
I have heard that global variables are bad and you better use "var" before the references. But is this a case where global variables are good?
-
UrbanConor over 2 yearsDoes this answer your question? How to get a variable from a file to another file in Node.js
-
-
appsthatmatter about 11 yearsglobal variables are bad - I totally agree with that. But I could be, that the module has a dependency to a variable. Is there a way to pass this variable to the other js-file via the require function?
-
jmar777 about 11 years@jjoe64 Not sure I follow what you mean. You can effectively share any value you want through the
exports
object. -
designermonkey about 10 yearsThe OP is asking whether a variable can be defined in the main.js, and then used in module.js. I have the same requirement to define paths that are used over and over again.
-
jmar777 about 10 years@Designermonkey In that case you're probably better off having a config object with those types of values that can also be require()'d into a given file. Note that you can just do
global.foo = 'bar'
and then accessfoo
anywhere you'd like... but like I said in my original answer, that is almost never a good thing. -
designermonkey about 10 yearsThanks for that, I figured out how to do that, and it works a treat. Thanks for verifying I had the right idea :)
-
Rubén Marrero almost 10 yearsWhy are global variables bad? If I want to treat a module as an object is there any better way to store that object's propoerties/attributes?
-
BaldEagle over 6 yearsDo these fragments contradict? 1) "a variable declared with or without the var keyword got attached to the global object." and 2) "variables declared with the var keyword remain local to a module."
-
Mohamed Allal over 6 yearsjust a quick note to left out confusion that can arise at first spot: module.exports is what should be used! whatever your js file is called (ex: global.js). module is a node object that exist in the global scope! [so within global.js we use module.exports=.....]
-
Kashif Ullah almost 6 yearsI liked Scenario 2, but can these values be changed after we talk build? like most often we do, npm run build. Or do you know some way to be able to change values after build?
-
Felipe Pereira almost 6 years@KashifUllah not sure if I'm able to answer your comment just with the provided info, you may want to add a new question in the site
-
Ahmad Zahabi over 4 yearsit will success if you remove the 'let', and there is no need to the "module.exports.."
-
Mike Kormendy almost 4 years@designermonkey how did you do that, please elaborate?
-
designermonkey almost 4 yearsIt was 10 years ago. I have no idea now. I suspect it was like the answer above.
-
user1063287 over 2 yearsis there a way to update values from
module.js
(e.g name, city, company) in all files that import it, so that the updated values are accessible to all files that have imported it? is there something like a 'dynamic global variable' that can be accessed and edited by whatever module references it? i have a question with more context here.