Passing a parameter trough require-module to ES6 class in Nodejs - node.js

I am learning to use ECMAScript6 -styled classes in NodeJS (7.7.3). I have used this kind of programming style:
//app.js
var forecastHandler = require('./forecastHandler.js');
//forecastHandler.js
class ForecastHandler {
constructor() {}
}
module.exports = new ForecastHandler()
It has worked well until now, because I have to pass parameters to module.
//app.js
var forecastHandler = require('./forecastHandler.js')(3600);
//forecastHandler.js
class ForecastHandler {
constructor(cacheUpdateDelay) {}
}
module.exports = new ForecastHandler(cacheUpdateDelay)
I got this error: ReferenceError: cacheUpdateDelay is not defined.
Can I pass the parameter to ForecastHandler-module using ES6 styled classes and creating an object at module.exports? If I only export the class and create the object in app.js, code works, but it's syntax is ugly.
//app.js
var forecastHandlerClass = require('./forecastHandler.js');
var forecastHandler = new forecastHandlerClass(3600);
//forecastHandler.js
module.exports = ForecastHandler
EDIT: better examples

module.exports = new ForecastHandler(cacheUpdateDelay)
The trouble with this code is that it initialises the object when the code is first run.
require('./forecastHandler.js') means "execute all the code in forecastHandler.js and give me the exports object. This means that the JS engine tries to run new ForecastHandler(cacheUpdateDelay) when there is no cacheUpdateDelay created.
The simple way to do this is the one you provide. Load the class, then try to make a new instance of it. If you really want to one-line it, you can do this in app.js:
var forecastHandler = new (require('./forecastHandler.js'))(3600);
There are various other ways you could do this. The simplest involve not exporting a class but a function.
For instance, you could do this in your module file:
module.exports = cacheUpdateDelay => new ForecastHandler(cacheUpdateDelay);
// OR
module.exports = function(cacheUpdateDelay) {
return new ForecastHandler(cacheUpdateDelay);
};

Related

Node JS, exporting a class and cosumin it with different name

I'm using Node v14.4.0. I created a file and named it 'dao.js'. The file includes the following:
class AppDAO {
// some constructor and functions
}
module.exports = AppDAO
In my app.js file I load it using
const dao = require('./dao');
const db = new dao();
It works fine, but I don't know why, shouldn't I use the class name as I set it, "AppDAO", instead of "dao"?
This link as well as other links, do not help me in understanding how require modules works.
Is there something that I am missing?
You can do this
file dao.js
class AppDAO {
// some constructor and functions
}
exports.AppDAO = AppDAO;
and in app.js
const dao = require('./dao');
const db = new dao.AppDAO();
You are exporting the class from the file you are requiring, so you have to write it like this.
const dao = require('./dao');
const db = new dao.AppDAO();

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.

NodeJS module with parameters

I want to create a module with socket.io parameter so I would have a globally set variable in my module class.
My question is how would one do it and still access the functions in that model class?
in term I would want something like what you can do with socket.io lib,
this is how you define the socket.io lib in the main app class and you can see that you need to pass a server parameter and you can use the objects funnctions.
const io = require('socket.io')(server);
Also this is the exact object I want to pass to my model.
Model file:
var storedObject
module.exports = (myObject) => {
if(myObject){
// set object only if provided
// this way you will be able to init once and use everywhere this model
storedObject = myObject
}
return {
getA: getA
}
}
function getA(){
return storedObject.a
}
Usage example:
var obj = {a: 1, b: 2} // can also be a socket.io or any other object
var model= require('./model.js')(obj) // call with object only on initialization
console.log(model.getA())

Use Singleton Throughout All Node.js Modules

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);
}
};

Exporting a prototype in node.js: module.exports=Prototype or exports.Prototype=Prototype?

What is the preferred way to export a prototype in node.js? You can take two approaches:
Export the prototype itself
function A () {
}
module.exports = A;
which is used as:
var A = require('./A.js');
var a = new A();
Export an object containing the prototype as property
function A () {
}
exports.A = A;
which is used as:
var A = require('./A.js').A;
var p = new A();
The first solution looks much more convenient to me, though I know there are concerns about replacing the exports object. Which of the two is best to use and why?
The second one would only be useful if you exported multiple classes from one file which is something that is questionable by itself.
There is no problem in replacing the exports object at all.

Resources