Use Singleton Throughout All Node.js Modules - node.js

I want to somehow create a global singleton module. I'm using it as the context module where I can reference it in any of my modules.
I'll use it to get to my gateway (repository) module for use in other modules like my business object modules etc. So for example let's say I have:
myBusinessModule.js
module.exports = {
find: function(id){
var user = context.userGateway.find(id);
}
};
So I want to be able to use the context singleton to get at other modules in my node app.
Just like the same thing here, this is Java but same concept I want to do something like this in Node.JS: CleanCodeCaseStudy

Based on your comment, to me it looks like you want something like this. Please correct me if i wrongly understood your requirement.
Access with require()
context.js
var context = {};
context.userGateway = require('../path/to/userGateway/module');
module.exports.context = context;
=====================================================================================
//usage in reference file
var context = require('/path/to/context/file');
module.exports = {
find: function(id){
var user = context.userGateway.find(id);
}
};
Access without require()
var context = {};
context.userGateway = require('../path/to/userGateway/module');
GLOBAL.context = context; // makes your context object accessible globally, just like, console, require, module etc.
=====================================================================================
//usage in reference file
module.exports = {
find: function(id){
var user = context.userGateway.find(id);
}
};

Related

Imported module is undefined when there's a circular dependency between the modules when one module is in the parent directory of the other module

file structure is
-src
--Visitor
---visitor.model.js
---Sessions
----session.model.js
In visitor.model.js file
const {Sessions} = require('./Sessions/session.model');
const Visitor = {};
Visitor.visitorFunc = () => {
}
Sessions.sessionFunc();
module.exports = {Visitor: Visitor};
In session.model.js file
const {Visitor} = require('../visitor.model.js');
const Session = {};
Sessions.sessionFunc = () => {
}
Visitor.visitorFunc();
module.exports = {Session: Session};
when I do imports like this in Visitor file Session is undefined. What is the reason for that.. Is it calling import recursively ?
Circular dependencies are allowed in node
https://nodejs.org/api/modules.html#modules_cycles
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
Since Session and Visitor sounds like database models with an M:N relationship circular dependencies are the way to go (e.g.: Join query)
How to deal with cyclic dependencies in Node.js
Node.js Module.Exports Undefined Empty Object
But it would be less messy to avoid them if you can.
As #prashand above has given the reasons you would have to do imports and calling imported functions after exporting current module.. above example is working with a slight change as follows
const Visitor = {};
Visitor.visitorFunc = () => {
console.log('hello from visitor model');
}
module.exports = {Visitor: Visitor};
// import session.model after exporting the current module
const {Session} = require('./Sessions/session.model');
// then call the required function
Session.sessionFunc();
Simply just use exports.someMember = someMember instead of module.exports = { someMember }.
Your visitor.model.js file is outside the Sessions directory. In order to import session.model.js you need to give absolute path to that file. So your require statement should be like this
const { Sessions } = require('../Sessions/session.model.js');

NodeJS requiring modules, module.exports.X vs module.exports={x}

I'm having trouble understanding the difference between exporting modules like:
module.exports.getUserIP = function getUserIP(req) {
var ip = req.headers['x-forwarded-for'];
return ip;
}
Or just declaring it:
function getUserIP(req) {
// retrieve user IP from req object
// Build this function to be more accurate/use more sources.
var ip = req.headers['x-forwarded-for'];
return ip;
}
and exporting at the bottom:
module.exports = { getUserIP }
or even:
module.exports = {getUserIP:getUserIP}
or
module.exports = {'getUserIP':getUserIP}
My problem is: when i call the function getUserIP from another file:
var mainbody = require('./app.js');//getUserIP is in here.
const gl = require('geoip-lite');
var ax = require('axios');
module.exports.getloc = function getloc(req, ip, property) {
//return location from IP.
if (req) {
var ipGuest = mainbody.getUserIP(req); //HERE
} else {
var ipGuest = ip;
}....
I get an error message:
Error Message
However, when I use the FIRST method to export the function:
module.exports.getUserIP = function getUserIP(req) {
var ip = req.headers['x-forwarded-for'];
return ip;
}
Then it works perfectly.
What's the difference?
Better way is to use
module.exports = { getUserIP: getUserIP }
This way you can just look at the export statement at the end of your file and know which functions are being exported from a particular file
The module.exports = {getUserIP}; is nothing but a shorthand of the above syntax(ES6 Magic). What it typically does is allows you to write this way { getUserIP } if the key name to be same as function/variable name like { getUserIP: getUserIP } where getUserIP can be a variable or a function or a ES6 class.
All the examples you show will work properly, but they do have some different affects.
By default module.exports is already initialized to an empty object. So, when you do something like this:
module.exports.getUserIP = function() {...}
You are assigning a new property to the existing object that module.exports already pointed to. One advantage of this scheme is that you can easily add more properties the same way.
module.exports.getUserRegion = function() {}
This will add one more property to that same object without disturbing the first one you already added.
On the other hand, all of these are identical:
module.exports = {getUserIP: getUserIP}
module.exports = {'getUserIP':getUserIP}
module.exports = { getUserIP } // ES6 shorthand for the previous syntax
and, they all end up with the same result as each other, but they all replace module.exports with a new object that has your one new property in it.
If you then tried to add another property:
module.exports = {getUserRegion};
That would again assign a whole new object to module.exports and you would have just wiped out the object that previously had getUserIP on it. When assigning a new object, you would typically assign an object that had all your properties on it:
module.exports = {getUserIP: function() {...}, getUserRegion: function() {...}};
Thus, not wiping out something you had already put there.
All of your schemes should work fine as long as you aren't overwriting module.exports with a new object and thus overwriting the object that already had some of your methods on it.
To understand this exporting modules concept, just think module.export is a simple object. you can bind anything to that object as do with normal javascript objects.
Finally when you require that module by require('path to js') you will get that exported object. If you export number of items in your module you can return them back by giving the names of the tag.

Access variable in main node file from an imported file

//in app.js
var x = require("x.js");
var instanceX = new x();
require("./Weather")();
//in Weather.js
instanceX.getName();
In this case instanceX wouldn't exist when referenced from Weather.js. How do I make instanceX accessible in Weather.js?
There are a number of different ways to approach this in module design. One simple way is to just pass the variable to the weather.js constructor:
//in app.js
var x = require("x.js");
var instanceX = new x();
require("./Weather")(instanceX);
//in Weather.js
var instanceX;
module.exports = function(ix) {
instanceX = ix;
}
// then elsewhere in the module
instanceX.getName();
I refer to this as the "push" model because you're pushing things to the module that you want to share with it.

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

Dynamic require in Nodejs

I'm requiring a library in NodeJS which has a self-invoking function, that results an error because it looks for an object which is not initialized at that moment .
I want to dynamically require this library when that object is initialized.
Is there any way to dynamically require/ load a library ?
This is the part of library required :
https://github.com/sakren/node-google-maps/blob/develop/lib/Google.js#L5
Actually I want to require when the window object is present (client-side rendering).
So something like this :
'use strict';
var React = require('react');
var Map = require('./map.jsx');
var Common = require('../common/common');
var MapStatic = require('./map-static.jsx');
exports.type = function() {
return 'map';
};
exports.jsx = function(data) {
if (Common.isServerSide()) {
return (<MapStatic data={data}/>);
} else {
return (
<Map data={data}/>
);
}
};
exports.transform = require('./map-transform.js');
The reason the code looks weired is that I'm using react.
In nodeJS require can be used anywhere at anytime whithout much limitations AFAIK.
Which error is thrown once you require at runtime ?
In your else branch.
Try the following.
requires = {}
function getter(key) {
if(!requires[key]){
requires[key] = require(key)
}
return requires[key]
}

Resources