How to avoid using global? - node.js

I have very small nodejs app. Inside this application I define a model object in app.js like so:
global.model = {
name: 'Foobar'
};
The model is not persisted to any storage but kept in memory all the time. My requirement is, to be able to read and modify this model inside any module of my app.
I read that it is bad practice to use global. What is the better way? Through exports? Can you explain?

You can have a single module that creates and stores the model. Then, any other module that wants to get the model can require() your model module and then call a method on it to fetch the single shared model.
in model.js:
var mymodel = {
name: 'Foobar'
}
module.exports.getModel = function() { return mymodel;}
in any other module that wants to get the model:
var mymodel = require('./model').getModel();
If your model module would not generally be used for other things, then you could simplify it like this:
var mymodel = {
name: 'Foobar'
}
module.exports = function() { return mymodel;}
in any other module that wants to get the model:
var mymodel = require('./model')();

Related

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())

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

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

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

Avoiding multiple instances of the Sequelize class

I'm trying to build out a basic database schema using Express and Sequelize. I define all of the models in separate files. I have a single file (models/index.js) where I create an instance of the Sequelize class, import the models, and establish the relationships among the models. I also have multiple controllers that each need to have access to the models exported from models/index.js.
Here's the file where the models are imported:
// models/index.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('myApp', 'username', 'password');
var User = sequelize.import('./users');
var Contact = sequelize.import('./contacts');
var Conversation = sequelize.import('./conversations');
var Medium = sequelize.import('./mediums');
User.hasMany(Contact);
Contact.belongsTo(User);
Contact.hasMany(Conversation);
Conversation.belongsTo(Contact);
Medium.hasMany(Conversation);
Conversation.belongsTo(Medium);
module.exports.Sequelize = Sequelize;
module.exports.sequelize = sequelize;
module.exports.User = User;
module.exports.Contact = Contact;
module.exports.Conversation = Conversation;
module.exports.Medium = Medium;
Here's one of the controllers that needs access to the models.
// controllers/users.js
var models = require('../models');
module.exports.addUser = function () {
};
module.exports.getUser = function () {
};
Here's another controller that needs access to the models.
// controllers/contacts.js
var models = require('../models');
module.exports.addContact = function () {
};
module.exports.getContact = function () {
};
module.exports.getAllContacts = function () {
};
My concern relates to the fact that both controllers require the models/index.js file. Each time the models/index.js file is required, a new instance of the Sequelize class is created, which establishes a new connection to the database. Does anybody have any suggestions to avoid multiple instances of the Sequelize class?
Thanks in advance!
Modules (files) are cached in node:
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
Multiple calls to require('foo') may not cause the module code to be executed multiple times. This is an important feature. With it, "partially done" objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export a function, and call that function.
https://nodejs.org/api/modules.html#modules_caching
This means, that the code on models/index.js will only be run once

Node.js - passing object with require

I am pretty certain there is a way to pass a variable using require.
So it would look something like this:
var model = require('model')(mongoose);
With the above line of code, I want to pass my model file my database information (mongoose), so that if I access the same model with a different database, I can pass it different database information.
However, even if the above syntax is correct, I am not sure what my model file itself would have to look like. Can anyone help me out with this?
module.exports = function (mongoose) {
// . . .
return model;
};
You can pass moongoose by argument to that file
var model = require('model')(mongoose);
Your module will look like this, you can make an object in module.exports and can attach multiple properties to that object and in the end return it from the function
module.exports = function (mongoose) {
model ={};
model.properties = {};
model.yourfunction1 = function(){};
return model;
};
I guess I can't assign anything else to module.exports in this case?
Answer to your comment is explained below
Choosing between module.exports and exports depends on you
For exports
exports.object1 = {};
exports.object2 = {};
For module.exports
module.exports = function(){
myobj={}
myobj.object1 = {};
myobj.object2 = {};
return myobj
}
Now calling it will be different
For exports it will be directly available on file variable
var file = require('./file');
console.log(file.object1);
For module.exports you will execute it like a function by appending function parenthesis so that object can be returned
var file = require('./file')();
console.log(file.myobj.object1);

Resources