In Javascript (Node.js), Is It Possible To Pass an Already Instantiated Class Object into Another Code Module - node.js

I'm probably missing a larger point of Javascript here, but I wanted to ask the community if the answer is 'NO!'.
Let's say you have an index.js that requires a udp port module:
index.js:
let port1 = require(udp_port.js);
port1.start( { port: 1234, classObj: new myClassObj() } );
udp_port.js:
let dgram = require('dgram');
let msgProcessor; // This is the class obj I'm trying to pass in from index.js
let server = dgram.createSocket('udp4');
exports.start = function(configObj) {
msgProcessor = configObj.classObj; // Can I do this???
}
Any advice would be great at this point, thanks.

In Javascript (Node.js), Is It Possible To Pass an Already Instantiated Class Object into Another Code Module
Yes, it is perfectly possible to pass an instantiated object created in one module to another module. That is done all the time.
Integers and Strings absolutely, but can you pass in a class object? Something you instantiated with the keyword 'new'?
Yes, something instantiated with new can be passed. There are no limitations on what you can pass. Any Javascript type of data. Separate modules loaded into the same nodejs program all run in the same Javascript interpreter. There are no limitations at all on how they can share data with each other.

#James Yep, I had code that I ran before posting but saw mixed results. The code I put in this post was code I cut out of my program. I ended up solving the problem though. What I thought was a limitation of passing variables, was actually a problem related to globals inside a container module (that the instantiated class object was getting passed into).
I was declaring multiple container variables and the global inside was getting reassigned/overwrote with each instantiated class object I passed in.
port1.start(...);
port2.start(...);
had 'msgProcessor' getting assigned twice. Yikes!

Related

how to pass a shared variable to downstream modules?

I have a node toplevel myapp variable that contains some key application state - loggers, db handlers and some other data. The modules downstream in directory hierarchy need access to these data. How can I set up a key/value system in node to do that?
A highly upticked and accepted answer in Express: How to pass app-instance to routes from a different file? suggests using, in a lower level module
//in routes/index.js
var app = require("../app");
But this injects a hard-coded knowledge of the directory structure and file names which should be a bigger no-no jimho. Is there some other method, like something native in JavaScript? Nor do I relish the idea of declaring variables without var.
What is the node way of making a value available to objects created in lower scopes? (I am very much new to node and all-things-node aren't yet obvious to me)
Thanks a lot.
Since using node global (docs here) seems to be the solution that OP used, thought I'd add it as an official answer to collect my valuable points.
I strongly suggest that you namespace your variables, so something like
global.myApp.logger = { info here }
global.myApp.db = {
url: 'mongodb://localhost:27017/test',
connectOptions : {}
}
If you are in app.js and just want to allow access to it
global.myApp = this;
As always, use globals with care...
This is not really related to node but rather general software architecture decisions.
When you have a client and a server module/packages/classes (call them whichever way you like) one way is to define routines on the server module that takes as arguments whichever state data your client keeps on the 'global' scope, completes its tasks and reports back to the client with results.
This way, it is perfectly decoupled and you have a strict control of what data goes where.
Hope this helps :)
One way to do this is in an anonymous function - i.e. instead of returning an object with module.exports, return a function that returns an appropriate value.
So, let's say we want to pass var1 down to our two modules, ./module1.js and ./module2.js. This is how the module code would look:
module.exports = function(var1) {
return {
doSomething: function() { return var1; }
};
}
Then, we can call it like so:
var downstream = require('./module1')('This is var1');
Giving you exactly what you want.
I just created an empty module and installed it under node_modules as appglobals.js
// index.js
module.exports = {};
// package.json too is barebones
{ "name": "appGlobals" }
And then strut it around as without fearing refactoring in future:
var g = require("appglobals");
g.foo = "bar";
I wish it came built in as setter/getter, but the flexibility has to be admired.
(Now I only need to figure out how to package it for production)

node.js setting a global variable

I'm new to node js. I searched a lot on stack overflow on this question below, none what I need.
I have an app.js file which initiates node server and a router file. I want to be able to store a global value once and shared across other server side .js files which contains my functions. I also want this variable to be accessible in my .jade file. (I use express BTW)
Is there a way to accomplish this?
Thanks.
The Node.js documentation says under Module Caching
Caching 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.
Which means you can easily expose a global object simply by putting it in its own module.
//config.js
var config = {
dbUrl: 'mogodb://localhost:2107/persons'
};
module.exports = config;
And then when you want to gain access to that object, you simply do:
var config = require('./config');
And that's done, you get access to the same instance everywhere.
You'll want to limit the usage of global vars in Node. This is because unlike any other server side language, Node is a persistent process that share all request. So you cannot setup user state globally as those will be shared across all user accessing your site.
In raw node, there's two global context:
global.foo = 'bar';
// and the process object
process.some_var = 1;
In Express, you can setup application wide vars using app.set
But, most of the time you'll want to share data by adding them to the request or the response objects. That is because those objects are "user" specifics, unlike the global namespace.
For the template, you'll always want to pass in the context:
app.render('email', Object.assign( aSharedObject, {
specific: 'values'
}));
i would use process.env or if you are using nconf put it into the app configuration as Jordan said, globals are BAD idea, also if you don't want to include nconf or any other conf module or use process.env then you can create a module and export a set of getters and setters to handle the value

Global variable with initialization callback

I use a third-party module (a spell-checker) that has a long initialization process, and calls a callback after the initialization is complete.
I need to use this module in several different files (sub-modules) of my application.
It looks like a waste of time and space to initialize a different spell-checker in each sub-modules, so I am looking for a way to initialize a single spell-checker and use it in all modules.
One option I thought of is to put a spell-checker instance in a sub-module, initialize it in the sub-module, and require that sub-module from my other sub-modules. But, I don't know how to deal with the initialization callback - how can I make sure that my other sub-modules won't use the spell-checker instance before it is initialized?
Another option I thought of is to create a separate application that with the spell-checker, and contact it from my application via TCP/IP or another mechanism. But this also looks wasteful - too much communication overhead.
Is there a better way?
This is analogous to using a database driver library and waiting for it to connect successfully to the database before issuing queries. The most prevalent pattern seems to be for the asynchronous library to emit an event such as 'connected' and the calling code to not start interacting with the library until that event fires. The other option would be to follow the example of something like mongoose and queue bending calls until the spell checker is initialized and then begin submitting them for processing.
So in short I would wrap the spell checking in a small library that exports the spell checker directly, but also emits a 'ready' event when the underlying spellchecker library invokes the initialization callback. It should be possible to share this same instance of the wrapper module throughout your application.
Create your own module, checker.js, where
var spellChecker = require('wordsworth').getInstance();
var initialized = false;
module.exports = function (callback) {
if (!initialized) {
return spellChecker.initialize(/* data */, function () {
initialized = true;
callback (spellChecker);
}
}
callback (spellChecker);
}
client.js
var checker = require('./checker);
checker(function (spellChecker) {
// use it..
});
So, it will be initialized on first call, the rest of clients will use initialized version.

Returning a module in RequireJS

I'm refactoring a large javascript codebase to use RequireJS. Unfortunately, many of the files I'm dealing with are not object-oriented, and cannot return an object without significant modification. Is there a more efficient way to give 'dependent' modules access to the functions and variables contained in a module (without returning an object) ?
I have read about using the exports syntax for defining modules, but it is very unclear whether that would be a valid solution for this situation.
In a defined module, the exports object is what gets exported from the module and passed to whatever module requires it.
Consider this:
define(["exports"], function(exports){
exports.myCustomFunction = function(){};
exports.myCustomObject = {};
exports.myCustomVariable = true;
})
This module will place all the disparate functions and/or objects that you want made public onto the exports object.
At this point RequireJS will use that exports object to pass to a module that requires it:
require(["nameOfCustomModule|filename"], function(myCustomModule){
//evaluates to true
console.log(myCustomModule.myCustomVariable);
})
Here's a simple fiddle. Just bring up your console and you will see the value logged there. http://jsfiddle.net/xeucv/
Hope this clears it up a bit!

Is there a better way to structure global variables in Node.js?

Trying to understand what would be the best way to structure some variables. For example in my Node.js Express app, I have the following in app.js:
var poolModule = require('generic-pool');
global.pools = {
/* ... */
};
Where pools is my global variable that keeps track of MySQL and Redis pools. I am also wondering if I can do the same with actual Redis and MySQL objects (and maybe configs variable) so I don't have to require them all over the app. And since they are going to be used the most.
Is this bad practice, and if yes, what's a better way to structure this kind of code?
Edit: added global.
If you require a file you are actually always requiring the same object. So that means you can do:
module.exports = {
// same object for everybody that requires me
};
You have the right idea, but you want to use module.exports to export your object as a module. The CommonJS approach is to have local variables within the module and exported variables for use outside the module. In this way modules can access each others' variables through the use of require. These variables aren't really "global", but in a way are more like "friend" classes in C++. You can in fact have your poolModule do more than store variables for you--you could put methods and other functionality in there too and make it reusable across your whole application.

Resources