Cross-module variable in node.js - javascript

this question might have been asked already but all I find are specific case and I can't find a way to use the answers to solve my own problem.
What I want is a variable than has a single instance and is shared between modules/files
Let's say I have app.js and module.js
app.js:
var mymodule = require('./modules/mymodule.js');
var testVar = 'test';
...
mymodule.js:
var mymodule = {count:0}
var logCount = function() {console.log(mymodule.count);}
module.exports = mymodule;
Then with this code when app execute mymodule.count = 1, if after mymodules.js run logCount() it will log 1, this means that app and mymodule are sharing the exact same instance of mymodule.count
Now how can mymodule.js access to the same instance as testVar used by app.js in a way that if app.js change it's value, mymodule will have the same new value.
For exemple in normal javascript, if you include two scripts in an html page, as long as the variable isn't inside a function, every javascript file can access the variable, because it works as if all the script would have been pasted inside a single file, isn't there a way to obtain the same result in node?

Related

How to add value to global object from module in Node.js

I'm trying to add some value to the global or local object, but nothin happens.
I'm tried create:
global.test = {}; in main.js
And to add value test[name] = value in second js
tried create var test = {}; in second.js
And to add value test[name] = value in second js
But this examples doesn't helped me.
Code in my files:
main.js:
global.common = require('./second.js');
global.test = {}
second.js:
module.exports = {
main: function (name, value) {
test[name] = value;
}
};
second.js invoked in another files, but the whole point is displayed in the code above.
Reading the NodeJS docs:
In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module.
Seems like you are expecting the global scope of NodeJS to work the same way that JS works in browsers but that is not the case.
See this question for more information : What is the 'global' object in NodeJS

What happens when using "require()" in Node.js?

Sorry if this is a dumb question but I'm new to JavaScript/Node.js. This code below eludes me and I've done a fair bit of research... My questions below are more specifically related to instantiation.
I don't understand this:
var myApp = require('express');
var myCode = myApp();
How I see that it should be for instantiation:
var myApp = new Express();
var myCode = myApp.insideExpress();
How anonymous function expressions are:
var myApp = function();
var myCode = myApp();
If the word "require" acts as a sort of anonymous function expression, then how are things instantiated in the background? This is very important for making proper patterns, no?
My questions are:
What's happening in the background for the first example, is JavaScript/Node.js instantiating/constructing or not at all?
Are people who do this just creating bad patterns? Why should I use this pattern?
If no instantiation, then why not?
Thanks in advance
const myVar = require("someModule") loads a module from the file system, runs the module initialization code and assigns the module exports to your variable. The module loading sub-system maintains a cache so if it was previously loaded, it is not loaded or run again, the module's exports are just retrieved from the cache and assigned to your variable.
So, when you do this:
var myApp = require('express'); // load express module, assigns exports to myApp
var myCode = myApp(); // calls myApp() function and assigns result to myCode
The first line loads the express module and assigns the exports from that module to your myApp variable. In this particular case (it varies from module to module), the exports from the Express module is a function. So, after that first line of code, myApp contains a function which happens to be a factory function for creating new Express app objects.
The second line of code calls that factory function which returns a new Express app object.
A module can export anything it wants. In the case above, it exported a function, but it's also common to export an object that has a whole bunch of properties which you can then access. You can also export a constructor in which case the caller would then use new with the constructor to create a new object from it.
In the Express module, it did not export a constructor (which is why you don't use new with it). Instead, it decided to export a factory function that, when called, creates and returns a new object. This is just a design decision that can go either way depending upon the needs of the module and the whims of the code writer.
I can't really tell what you're asking here with this code:
var myApp = new Express(); // the express module does not export a constructor
var myCode = myApp.insideExpress();
This would work only if Express was a constructor function. The express module itself does not choose to export a constructor function so this is not how you use the express module. It could have been designed this way, but it was not. They simply made a different design decision when designing it.
For this other case you show:
var myApp = function();
var myCode = myApp();
That first line of code doesn't make any sense. Perhaps you meant for it to have a body to the function:
var myApp = function() { some code here };
var myCode = myApp();
In that case, myApp is being assigned a function expression (which is just one of several ways to declare a function). It's similar, though not exactly the same as:
function myApp() { some code here }
If the word "require" acts as a sort of anonymous function expression, then how are things instantiated in the background? This is very important for making proper patterns, no?
require('someModule) loads a module and returns the exports from the module which can be any Javascript data type. It doesn't act as an anonymous function in any way. require() is an actual function and you are just calling it and getting back its return value. Remember that in Javascript, you can return any data type from a function, include return another function (which is what the express module does).
What's happening in the background for the first example, is JavaScript/Node.js instantiating/constructing or not at all?
No instantiating or constructing. It's just loading a module, running its initialization code and return its exports. Some objects are created by the module loading system that are used for its own housekeeping, but the module itself is just initializing itself and then deciding what it wants to export.
Are people who do this just creating bad patterns? Why should I use this pattern?
Modules are highly useful in node.js development and it is considered good design to use proper module design. There are many, many advantages to good module design such as easier code maintenance, easier code testing, easier code reuse, easier code sharing, no need to create globals in order to share code, etc...
If no instantiation, then why not?
A module decides what it wants to export. It can, in its initialization code, create an instance of an object and export it. It can export a factory function that creates an instance of an object when called. It can export a constructor directly that lets the caller use new with it to create an instance of an object. It can export a utility function that just carries out some function and doesn't create any objects. It can export just data. It can export a plain object with multiple properties on it that have all sorts of possible uses. The possibilities are endless and it entirely depends upon what the purpose is of the module and what it wishes to share with the other module that loaded it.
It's just loading a library or a module into your script. It is not instantiating a new object. It's just making the loaded module's functions etc available to your current script. Here is a good writeup that I found,
http://fredkschott.com/post/2014/06/require-and-the-module-system/
I hope that helps answer your question.

Best way to share an instance of a module that is inside a closure [duplicate]

If I want to span my JavaScript project across multiple source files, but have each file have access to the same private variable, how would one do that?
For example, if I have the following code:
APP = (function () {
var _secret = {},
app = {};
// Application part 01:
app.part01 = (function () { /* function that uses _secret */ }());
// Application part 02:
app.part02 = (function () { /* function that uses _secret */ }());
//
return app;
}());
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
I don't want to pass it as an argument. That's just giving the secret away, as app.part01() could be replaced by any other function.
Maybe I am asking the impossible, but your suggestions might lead me in the right way.
I want to work with multiple files, but I don't know how. Copying and pasting everything inside a single function each time before testing is not something I want to do.
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
That's impossible indeed. Script files are executed in the global scope, and don't have any special privileges. All variables that they will be able to access are just as accessible to all other scripts.
Copying and pasting everything inside a single function each time before testing is not something I want to do
What you are looking for is an automated build script. You will be able to configure it so that it bundles your files together, and wraps them in an IEFE in whose scope they will be able to share their private state. The most simple example:
#!/bin/sh
echo "APP = (function () {
var _secret = {},
app = {};" > app.js
cat app.part01.js >> app.js
cat app.part02.js >> app.js
echo " return app;
}());" >> app.js
The only way that you can share _secret is attaching it to the application object and then application object to the window object. Here is an example.
// FIRST JS FILE...
var application; // will be attached to window
(function(app) {
app.secret = "blah!"; // will be attached to application
})(application || (application = {}));
// ANOTHER JS FILE
var application;
(function(app) {
app.method1 = function(){ console.log(app.secret); }; // will be attached to application;
})(application || (application = {}));
console.log(application.method1()); // will display 'blah!' on the console
Working example on jsbin
One way I was able to accomplish this was to create a JS file that contained the global object.
// Define a global object to contain all environment and security variables
var envGlobalObj = {
appDatabase: process.env.YCAPPDATABASEURL,
sessionDatabase: process.env.YCSESSIONDATABASEURL,
secretPhrase: process.env.YCSECRETPHRASE,
appEmailAddress: process.env.YCAPPEMAILADDRESS,
appEmailPassword: process.env.YCAPPEMAILPASSWORD
}
module.exports = envGlobalObj
Then in the files I wish to reference this object, I added a require statement.
var envGlobalObj = require("./envGlobalObj.js");
This allowed me to centralize the environment and secrect variables.

Creating Node.JS Module

I have been creating software in NodeJS for years, but I have rarely ever looked into the module side of it, since I've never needed to do that stuff myself.
I have created a test.js file, which is my module, all it contains is this (i've tried this.host, self.host, var host ... nothing is working)
var tests = function () {
this.host = "http://127.0.0.1/";
};
exports = tests;
In my server.js I try and use it and I can never get host to actually output
var tests = require('./test.js');
console.log(tests);
console.log(tests.host);
I always get this output, saying that tests variable has no properties ... which I set in the module.
sudo node server.js
{}
undefined
The host variable as you defined it in the tests function is not accessible through tests's prototype.
This means that in order to access it, you should be creating a new instance of tests, using the new operator :
var Tests = require('./tests');
var instance = new Tests();
// Now you can access `instance.host`
Also, as David said, use module.exports to export your function.
Don't do exports = tests. Either do exports.tests = tests or module.exports = tests.
Basically, you have to first decide if you want your module to just have properties that can be directly accessed or if you want it to have a constructor function that creates an object when it is called that then has properties or it could even just be a regular function that you call that returns a value. You have mixed and matched the first two schemes (pieces of each) and thus it does not work. I will show you both schemes:
Here's the scheme where your module exports a constructor function from which you can create an object (when you new it):
// test.js module
var tests = function () {
this.host = "http://127.0.0.1/";
};
module.exports = tests;
// main module server.js
var Tests = require('./test.js');
var t = new Tests();
console.log(t.host);
And, here's the scheme where you just directly export properties:
// test.js module
module.exports = {
host: "http://127.0.0.1/"
};
// main module server.js
var tests = require('./test.js');
console.log(tests);
console.log(tests.host);
Keep in mind that whatever you assign to module.exports is what require() will return after it loads your module. So, in your first case, you're assigning a function that is intended to be a constructor function so you have to use it as a constructor function in order for it to work properly.
In my second example, I assign an object to module.exports so you can then treat it just like an object after loading the module with require(). That means you can then just directly access its properties as you would for an object.
console.log(tests()); will work if the you add return statement inside the function.

meaning of module.exports= function in node.js

I am taking first steps with node.js and obviously one of the first things i tried to do was exporting some data from a module, so i tried this simple case:
dummy.js:
var user = "rally";
module.exports = {
user:user
};
and than required it from a different file like this:
var dummy = require('./dummy.js');
console.log(dummy.user); // rally
So far so good, every thing works, but now i dived into code where there is this definition in the beginning of the module:
module.exports = function(passport,config, mongoose) {}
and i don't understand whats the meaning of it and how can i work with it.
just for trying to understand i defined some variables inside this abstract function but couldn't get their value from any other file.
any idea how can i export variables from module defined like this..? so for example i could require this module and get the "Dummy" variable and use it in a different file
module.exports = function(passport,config, mongoose) {
var dummy = "Dummy";
}
It works exactly the same as the first one does, only that it exports a function instead of an object.
The module that imports the module can then call that function:
var dummy = require('./dummy.js');
dummy();
any idea how can i export variables from module defined like this..?
Since functions are just objects, you can also assign properties to it:
module.exports = function(passport,config, mongoose) {}
module.exports.user = 'rally';
However I'd argue that this is less expected if a module directly exports a function. You are probably better off exporting the function as its own export:
exports.login = function(passport,config, mongoose) {}
exports.user = 'rally';
WHAT IS A MODULE?
A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file.
// dummy.js
var exports = module.exports = {};
The utility of dummy.js increases when its encapsulated code can be utilized in other files. This is achieved by using exports.
HOW ARE THEY INVOKED?
You could declare your functions outside of the module.exports block. Functions inside exports can be invoked exactly the same way as variables or any other object.
EXAMPLE
//dummy.js
var myVariable = "foo";
var myFunction = function(){
//some logic
};
module.exports{
myVariable : myVariable,
myFunction : myFunction,
myVariableTypeTwo : "bar",
myFunctionTypeTwo : function () {
//some logic
}
}
We can now access the publicly available methods of dummy.js as a property from any js file.
var dummy = require('./dummy.js');
dummy.myVariable; //foo
dummy.myFunction();
dummy.myVariableTypeTwo; //bar
dummy.myFunctionTypeTwo();
NOTE
In the code above, we could have replaced module.exports with exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.

Categories

Resources