How to avoid using global functions in NodeJS? - node.js

I have a global function in my main JS file and i need to call it several times from a module. I heard it is bad because it can create a function name collision between a local (from module) and a global function name (from main js). The global function can be called 100 times from the require module. Is there an alternative way to achieve the following without using global functions?
main.js with global function
const myMod = require('./module.js");
global.myGlobalFunction = function(param){
console.log("do something with",param);
}
module.js with the calls of the global function:
module.exports = function(){
myGlobalFunction("class");
myGlobalFunction("this");
myGlobalFunction("bubu");
// other jobs to do
}

The neater way to do it is to use modules like this:
module.js
class myGlobalUtil {
myGlobalFunction(param){
console.log("do something with",param)
}
get GetFromParam(myParam){
return this.myGlobalFunction(myParam);
}
}
module.exports = myGlobalUtil;

Related

Best way to invoke code inside a module in nodejs

From a performance perspective, is there any difference between invoking code by wrapping it in a function and then exporting it:
function doSomething () {
// doing something here
}
module.exports = doSomething();
And just requiring it without any exports? like this:
myModule.js
// Code doing something
file that requires the module:
var doSomething = require('./myModule');
And if the purpose of the code inside the module is to run just once, do I need to store it in a variable?
If you don't need the return value of that function, then you don't have to store it in a variable.
The difference with:
function doSomething () {
// doing something here
}
module.exports = doSomething();
and using:
var x = require('module');
var y = require('module');
vs.
function doSomething () {
// doing something here
}
module.exports = doSomething;
and using:
var x = require('module')();
var y = require('module')();
is that in the first case, the function will be run only once, while in the second case the function will be run twice.
The difference is that if you just include it without module.exports, then the code will execute immediately but be private to the module. You can only access the data if you export it somehow, with module.exports. It can be either a function or a Javascript Object. Essentially, you can view everything within the module as being completely hidden from everything else in your application.
The only shortcut that I know of is for JSON files. If you look here: Module.exports vs plain json for config files, you can see that you can require('file.json') and it will replace the contents of the json file with a Javascript object that you can then use in your application.

How Do I create a NodeJS Module?

I have read the details on NodeJS site : https://nodejs.org/api/modules.html. I don't understand how modules work, and what are the minimal steps for creating a module, and how npm can help me.
How can I create a module?
How do I use a module?
What does putting it on npm mean?
Note: this is a self answered question, with the purpose of sharing knowledge as a canonical.
You can create a NodeJS module using one line of code:
//mymodule.js
module.exports = 3;
Then you can load the module, by using require:
//app.js
require('./mymodule.js')
I added './' because it is a module of one file. We will cover it later.
Now if you do for example:
var mymodule = require('./mymodule.js');
console.log(mymodule); // 3
You can replace the number 3, with a function, for example:
//mymodule.js:
module.exports = function () {
console.log('function inside the module');
};
Then you can use it:
var mymodule = require('./mymodule.js');
mymodule();
Private variables:
Every variable you define inside A module will be defined only inside it:
//mymodule.js
var myPrivateVariable = 3;
publicVariable = 5; // Never user global variables in modules
//It's bad-pracrtice. Always add: var.
module.exports = function() {
// Every function of the module can use the private variables
return myPrivateVariable++
};
//app.js
var mymodule = require('./mymodule.js');
console.log(mymodule()); // return 3
console.log(mymodule()); // return 4
Reuse modules:
One more thing you need to know about NodeJS modules, is that if you use the same module twice(require it), it will return the same instance, it will not run in twice.
for example:
//app.js
var mymodule1 = require('./mymodule.js');
var mymodule2 = require('./mymodule.js');
console.log(mymodule1()); //return 3
console.log(mymodule2()); //return 4 (not 3)
console.log(mymodule1()); //return 5
As you see in the example below, that private variable is shared between all the instances of the module.
A module package
If your module contain more than one file, or you want to share the module with others, you have to create the module in separate folder, and create a package.json file for the module.
npm init will create package.json file for you.
For modules, there are 3 required parts:
package.json
{
"name" : "You module name",
"version" : "0.0.3"
}
Now, you can publish the module, using npm publish. I recommend you publish all your modules to github as well, then the module will be connected to your github page.
What you publish to NPM will be accessible by everyone. So never publish modules that contain private data. For that you can use private npm modules.
Next steps
Modules can return more than one function or one variable. See this samples in which we return an object.
module.exports.a = function() {
// ..
};
module.exports.b = function() {
// ..
};
// OR
myObj = {
a:3,
b:function() {
return this.a;
}
};
module.exports = myObj;
More info:
Read about package.json files
Versioning in you modules best practice
More best practive for NodeJS modules
Private modules, using private npm
Related Questions:
What is the purpose of Node.js module.exports and how do you use it?
module.exports vs exports in Node.js
Creating module in node.js is pretty simple!!!
You may consider module as a set of functionalities you can use in other code by simply just requiring it.
for eg:Consider a file functional.js having the content:
function display(){
console.log('i am in a display function');
}
module.exports = display;
Now just require it in any other module like:
var display = require('./functional');
display()
Output:i am in a display function
Similarly you can do:
var exports = module.exports = {};
exports.display = function(){
console.log('i am in the display function');
}
or you do the same for objects like:
var funObj = {
hello:function(){
console.log('hello function');
},
display:function(){
console.log('display function');
}
};
module.exports = funObj;
There are two main ways for wiring modules. One of them is using hard coded dependencies, explicitly loading one module into another using a require call. The other method is to use a dependency injection pattern, where we pass the components as a parameter or we have a global container (known as IoC, or Inversion of Control container), which centralizes the management of the modules.
We can allow Node.js to manage the modules life cycle by using hard coded module loading. It organizes your packages in an intuitive way, which makes understanding and debugging easy.
Dependency Injection is rarely used in a Node.js environment, although it is a useful concept. The DI pattern can result in an improved decoupling of the modules. Instead of explicitly defining dependencies for a module, they are received from the outside. Therefore they can be easily replaced with modules having the same interfaces.
Let’s see an example for DI modules using the factory pattern:
class Car {
constructor (options) {
this.engine = options.engine
}
start () {
this.engine.start()
}
}
function create (options) {
return new Car(options)
}
module.exports = create

How to share a certain instance with multiple modules in Node.js?

Suppose that I have my main.js module, a shared.js and a foo.js modules.
main.js file is the following:
function Main(){
this.shared = new Shared();
}
Main.prototype.getFoo(){
return new Foo();
}
Now, in order to work Foo needs the 'shared' instance created in Main, Is there an approach I could take other than passing 'shared' to Foo so that Foo can always access that 'shared' instance?
Edit: Main is instantiated once.
You may use global variables to do this but this is not the propper way. Far better you can use require() to do this. In the main.js add the following:
module.exports = Main;
Now in any other module you need this only require it.
var Main = require('./main.js');
That's it. This works also between different packages.
I was able to solve this problem by directly passing the shared instance to the exports.
shared.js:
module.exports = new Shared();
function Shared(){
...
}
main.js:
function Main(){
this.shared = require('./shared.js');
}
Main.prototype.getFoo = function(){
return new Foo();
}
foo.js:
function Foo(){
this.shared = requrie('./shared.js');
}
This way Foo will use the same 'shared' instance used in Main without having to pass it. I'm not sure if this is a 'correct' way to achieve my needs but is doing its job.

Scope of JS Functions outside Node Modules

I know that in Node, if you've got variables defined outside your module.exports, it's still locally meaning it's not poluting the global namespace. It's not public. What's public is what's defined in your module.
However what about functions. Do they act the same as variables? Could function names that live outside module.exports collide?
example:
myFirst.js
var iAmStillPrivate = "private";
module.exports = {
...whatever code I wanna expose through this module
}
function find(somethingId)
{
..some code
};
mySecond.js
var iAmStillPrivate = "private";
module.exports = {
...whatever code
}
function find(somethingId)
{
..some code
};
do the find() conflict and pollute the global namespace?
Should I do this instead?:
mySecond.js
var iAmStillPrivate = "private";
module.exports = {
find: find(id)
...whatever code
}
var find = function find(somethingId)
{
..some code
};
or doesn't it matter throwing it into a variable? good practice? doesn't really matter?
CONCLUSION
mySecond.js (I'm a mother fu**ing module. I create an implicit anonymous function that wraps everything in here when I'm 'required' inside other .js files)
`var iAmStillPrivate = "private";` (no I'm scoped to the module, the root anonymous function that is...)
(module.exports - I'm allowing this stuff to be public. When I say public in node,that is...public in that the stuff in here is accessible to other modules in other .js files or whatever.)
module.exports = {
...whatever code
}
(I'm still a function scoped to the module but I've not been exported so I'm not available to other modules, I only belong to the module (the root anonymous function)
function find(somethingId)
{
..some code
};
Functions in each module of NodeJs are local for that module and do not conflict with functions of other modules with the same name.
Think about it as though the module was wrapped in a function.
Also you really don't need to define a variable for your functions because at the end it doesn't matter, the scope of functions and variables of these two lines are the same and local for module:
var find = function find(somethingId) ...
function find(somethingId) ...
Side Question
Also in you comment you asked about this scenario:
what if I have a function in global scope and a module also has a private function with the same name. do they conflict?
What happens is that inside your module any call to that function will trigger the local function not the global one. once you are outside of that module or inside another modules any call to that function will trigger the global function.
Let's look at it with an example. suppose our Node app starting point is index.js here its content:
echo('one');
require('./include.js')
echo('three');
function echo(txt){
console.log("we are in index.js", txt);
}
And here is a module called include.js:
echo('two');
function echo(txt){
console.log("we are in include.js", txt);
}
if you run this app using node index.js command, the output should be:
we are in index.js one
we are in include.js two
we are in index.js three
See? All the functions are there working as I explained earlier.

Node.js inherit local variables

I have a variable in my server.js, lets call it 'a'. When I require a module, it doesn't have access to the variable a. For example:
server.js
myModule = require('./myModule.js');
var a = 'Hello!'
myModule.say();
myModule.js
exports.say = function () {
console.log(a);
}
How can I make it so myModule.js can access the variables in server.js without having function arguments?
server.js:
myModule = require('./myModule.js');
global.a = 'Hello!'
myModule.say();
myModule.js:
exports.say = function () {
console.log(global.a);
}
However, please keep in mind globals are usually discouraged in Node.js (and JavaScript in general). Isn't the point of a module to encapsulate certain functionality? If so, it shouldn't depend on outside variables existing or being defined.
Ideally, you want to pass in the required information into the module via some sort of initialization function or configuration parameters.

Resources