module.exports colliding / being overwritten in node.js application - javascript

I think I'm badly misunderstanding how to use module.exports. It seems every module is overwriting what the last one spit out.
app.js:
var express = require("express")
, app = express()
, routes = require('routes')
, server = app.listen(1337, "0.0.0.0")
, io = require('socket.io').listen(server)
, redis = require("redis")
, client = redis.createClient();
var moduleA = require("./moduleA")(io, client); (need to pass socket.io and redis client)
var moduleB = require("./moduleB")(io, client); (same)
moduleA.js:
module.exports = function(io, client){
this.test = 'foo';
return this;
};
moduleB.js:
module.exports = function(io, client){
this.test = 'bar';
return this;
};
back to app.js:
console.log(moduleB.test); (prints "bar")
console.log(moduleA.test); (also prints "bar")
Could someone explain what I'm doing wrong? I can't think of any other way to do this, since the exports helper (?) itself doesn't seem to accept parameters.

You are exporting a constructor. You need to construct it, not call it.
Change
var moduleA = require("./moduleA")(io, client);
to
var moduleA = new (require("./moduleA"))(io, client);
or (for clarity)
var ModuleA = require("./moduleA");
var a = new ModuleA(io, client);
What you are seeing happen is the usual behavior when calling constructors as functions in sloppy mode: this references the global object. So of course modifying the global object from two locations will overwrite each other, and returning this will just return the global object. You can test this yourself: with your current code,
moduleA === moduleB === this === global
One way to prevent yourself from ever shooting yourself in the foot like this again is to use strict mode instead of sloppy mode. To do so, add the line
"use strict";
at the top of every module you write (before any other code). In strict mode, this for constructors called without new is undefined, so you will get an earlier and much easier-to-understand error.
Strict mode has many benefits of this sort; for an overview see [1], [2], [3].
An alternate solution is to stop using constructors altogether, but instead use factory functions. This would look like:
module.exports = function (io, client) {
var result = {};
result.test = "foo";
return result;
};
You seem to be trying to do something like this anyway, since you return this even though doing so in a constructor is entirely unnecessary. You could just stop using this and use an actual object under your control, instead of one whose semantics change depending on whether your function is being called or constructed.

Related

Are same name functions in different classes supported in Nodejs?

Can nodejs have two functions in different classes with the same name ?
If not then why not ? otherwise there is something wrong in the code.
Following is the example;
var admins = require('./routes/admins');
var users = require('./routes/users');
Both singleton classes
var users = function users(){
this.foo = foo = function(bar){ ...
}
}
users.getInstance = getInstance = function(){
if(this.instance == null){
this.instance = new users();
}
return this.instance;
}
module.exports = users.getInstance();
The admin class is also similar, both the classes have the same function names as well.
Now when foo is called it gets called of user class no matter what.
If i change the require order the foo of admin class is called.
As literally written in your question, I don't see a reason why this would happen. However, you are leaking into global scope, and that's how you might end up with duplicates.
users.getInstance = getInstance = function(){ ...
First, notice that the middle getInstance isn't scoped with var, so it gets assigned to the global scope. While this doesn't cause immediate problems, you're still polluting global scope, which is bad.
The real issue appears if you just do:
module.exports = getInstance();
Whether or not you've scoped getInstance with var, you're calling it in the global context, which means that inside the function, this == global. This means that the first time the function runs, it is basically doing:
global.instance = new users();
...and when your second file runs, it sees there's already a global.instance and just returns it.
Consider using 'use strict'; so these kinds of errors are caught for you.
Finally -- why are you doing all these getInstance gymnastics? They are entirely unnecessary. Your users file should just look like:
exports.foo = function(bar) {
...
};
Since the function name are same and the code is executed in sequential order, the function inside the second class overrides the first.
So the function will be called from whichever file is in second place.

how to export variables from coffeescript in meteor packages

I'm confused by how to use exported variables with coffeescript meteor packages.
[edit] concrete example.
I followed various advice and have a JS file _defines.js
//defines.js
Ribot = {}
Then
# server.coffee
Meteor.startup ->
Ribot = new Bot()
Meteor.methods botReply: (obj) ->
reply = Ribot.reply("user", obj.text)
so the problem is that the Ribot object within the startup block is not available inside the meteor methods block.
When i write similar code with javascript:
Meteor.startup( function() {
Ribot = new Bot();
Meteor.methods({
botReply: function(obj) {
reply = Ribot.reply("user", obj.text)
things work fine.
the current hack to get around is define everything to hang off a share.Ribot as per meteor's coffeescript support.
So for step one I don't actually need to export the Ribot object outside the package since most of the interface is currently via Meteor.methods, however I will need to eventually.
details below
There are more complicated suggestions, but I found that what works in a package is the opposite of normal CS app development.
eg:
Rbot = {} # no # on declaration
Meteor.startup ->
#RBot = new Thing() # use # in references
console.log("new Rbot", #RBot)
and then in package.js
api.export(['RBot']);
it's now available to the app.
However, in normal coffeescript usage from within my app (not a package) the opposite is true. For example
# use # when declaring
#SceneData = new Meteor.Collection("SceneData")
Meteor.startup ->
if Meteor.isServer
Meteor.publish "SceneData", (query, fields) ->
# dont use # when referencing
return SceneData.find(query, fields)
This also seems different than how normal coffeescript works outside of meteor (see ex below).
Within the app i think this is maybe because meteor is calling methods with a "this" object the same as the top level window? So there's another layer of "magic" going on?
Whereas within a package Meteor is wrapping more closures than coffeescript itself.
If someone can suggest the "right" way to do this, or explain why these two opposite wrapping/#ref styles are needed in the same framework, that'd be enlightening.
compiler example:
#outer = "outer"
inner = "inner"
p1 = () ->
console.log #outer # wont run
console.log(outer)
p2 = () ->
console.log inner
console.log #inner
p3 = () =>
console.log #outer
console.log(outer)
p1()
p2()
p3()
// compiles to:
(function() {
var inner, p1, p2, p3;
this.outer = "outer";
inner = "inner";
p1 = function() {
console.log(this.outer);
return console.log(outer);
};
p2 = function() {
console.log(inner);
return console.log(this.inner);
};
p3 = (function(_this) {
return function() {
console.log(_this.outer);
return console.log(outer);
};
})(this);
p1();
p2();
p3();
}).call(this);
If you write #myVariable = value in a package, you don't need to export myVariable since there's no package variable named myVariable, because you have instead attached it as a new property to the global object. However, you should avoid doing this, since packages shouldn't modify the global object, but exporting some of its package variables instead.
However, package variables must be defined as global variables (in JavaScript: myVariable = value (and not var myVariable = value), and the downside is that there's no equivalent statement in CoffeeScript (in CoffeeScript myVariable = value compiles to var myVariable = value, which creates a file scoped variable). To solve this, the meteor folks introduced the shared variable (containing an object), and the idea is that package scoped variable should be assigned as properties to this object. Read more about it in the docs for CoffeeScript in Meteor.

Node.js make initialized object available in all modules

I have an initialized object that I initialized in app.js file and I would like to make this initialized object is available in all modules. How could I do that? Passing this object to every modules is one way to do and I'm wondering if I'm missing anything or there should be done in difference ways?
I saw mongoose actually support default connection, which I need to init in app.js one time and anywhere in other modules, I can just simply use it without requiring passing it around. Is there any I can do the same like this?
I also checked global object doc from node.js http://nodejs.org/api/globals.html, and wondering I should use global for issue.
Thanks
A little advice:
You should only very rarely need to use a global. If you think you need one, you probably don't.
Singletons are usually an anti-pattern in Node.js, but sometimes (logging, config) they will get the job done just fine.
Passing something around is sometimes a useful and worthwhile pattern.
Here's an example of how you might use a singleton for logging:
lib/logger.js
var bunyan = require('bunyan'),
mixIn = require('mout/object/mixIn'),
// add some default options here...
defaults = {},
// singleton
logger,
createLogger = function createLogger(options) {
var opts;
if (logger) {
return logger;
}
opts = mixIn({}, defaults, options);
logger = bunyan.createLogger(opts);
return logger;
};
module.exports = createLogger;
lib/module.js
var logger = require('./logger.js'),
log = logger();
log.info('Something happened.');
Hope that helps.
The solution, as you suggest is to add the object as a property to the global object. However, I would recommend against doing this and placing the object in its own module that is required from every other module that needs it. You will gain benefits later on in several ways. For one, it is always explicit where this object comes from and where it is initialized. You will never have a situation where you try to use the object before it is initialized (assuming that the module that defines it also initializes it). Also, this will help make your code more testable,
There are multiple solutions to the problem, depends upon how large your application is. The two solutions that you have mentioned are the most obvious ones. I would rather go for the third which is based on re-architecturing your code. The solution that I am providing looks alot like the executor pattern.
First create actions which require your common module that are in this particular form -
var Action_One = function(commonItems) {
this.commonItems = commonItems;
};
Action_One.prototype.execute = function() {
//..blah blah
//Your action specific code
};
var Action_Two = function(commonItems) {
this.commonItems = commonItems;
};
Action_Two.prototype.execute = function() {
//..blah blah
//Your action_two specific code
};
Now create an action initializer which will programmatically initialize your actions like this -
var ActionInitializer = function(commonItems) {
this.commonItems = commonItems;
};
ActionInitializer.prototype.init = function(Action) {
var obj = new Action(this.commonItems);
return obj;
};
Next step is to create an action executor -
//You can create a more complex executor using `Async` lib or something else
var Executor = function(ActionInitializer, commonItems) {
this.initializer = new ActionInitializer(commonItems);
this.actions = [];
};
//Use this to add an action to the executor
Executor.prototype.add = function(action) {
var result = this.initializer.init(action);
this.actions.push(result);
};
//Executes all the actions
Executor.prototype.executeAll = function() {
var result = [];
for (var i = this.action.length - 1; i >= 0; i--) {
result[i] = this.action[i].execute();
}
this.action = []
return result;
};
The idea was to decouple every module so that there is only one module Executor in this case which is dependent on the common properties. Now lets see how it would work -
var commonProperties = {a:1, b:2};
//Pass the action initilizer class and the common property object to just this one module
var e = new Executor(ActionInitializer, commonProperties);
e.add(Action_One);
e.add(Action_Two);
e.executeAll();
console.log(e.results);
This way your program will be cleaner and more scalable. Shoot questions if it's not clear. Happy coding!

Breaking my javascript into modules, am I doing this right?

I'm using the javascript module pattern, and have this so far:
var APP;
if(APP == undefined) {
APP = {};
}
APP = (function() {
var userId = -1;
var privateVar = '';
var _init = function($userId) {
userId = $userId;
};
var _publicMethod = function($id){
privateVar = id;
};
return {
init = function($userId) {
_init($userId);
},
publicMethod = function($id) {
_publicMethod($id);
}
};
})();
I then have a common utils module:
APP.utils = (function(){
})();
And then per page I am planning on having a module, so I don't wireup events (button clicks etc) for no reason on pages where these DOM elements don't event exist:
APP.homePage = (function(){
return {
};
})();
So each module will have a init() method that I will call on the page to run things that have to be run (e.g. wiring up events, setting variables like say userId etc):
$(document).ready(function() {
APP.init(<%= user.id %>);
APP.homePage.init('abc');
});
So now if the files get too big, I can break them out into separate files also.
What if one module needs to call another, I guess the only way for this to work is to do this via the public api right?
e.g. what if homePage needs userId, should I pass that in the homePage#init method?
How is my coding style, any obvious style that is not considered best practise?
Any comments on this approach? Is it good in general?
What if one module needs to call another, I guess the only way for this to work is to do this via the public api right?
Yes
e.g. what if homePage needs userId, should I pass that in the homePage#init method?
No. I'd not repeat the userId code in all modules, but offer a public getter for it in the default module.
Any comments on coding
This code
var APP;
if(APP == undefined) {
APP = {};
}
APP = ...
is quite useless. You don't need to check for object existance here, because you overwrite it anyway. That also means that this code must be the first to execute. If you want to make the modules independent from load order, you'd need to use something like
var APP = (function(a) {
var private_vars; // ...
a.init = ...
a.publicMethod = ... // add them to the object instead of creating new one
a.getPrivate = function() {
return private_vars;
};
return a;
})(APP || {}); // create one iff not already existing
// other file:
var APP = APP || {};
APP.utils = ... // add object to namespace
The code
var _publicMethod = function($id){
privateVar = id;
};
looks a bit odd. First, the underscore usually denotes a semiprivate (public-but-not-to-be-used) attribute of objects and should not be used for variable names. That's not the case in here as the function will be exposed as the "publicmethod" property of APP. Use the underscore there if you want it. Second, there is no need to use a function expression here. The code is in the module's local scope, and using a function declaration both makes it available everywhere in that scope and allows naming the function. You should use
function publicMethod($id) {
privateVar = id;
}
a.publicMethod = publicMethod;
The module pattern is, in my opinion, a really nice way to organize your code. To answer your questions:
1) Yes, your modules can only access methods and properties of other modules which have been exposed in the object they return.
2) I think your coding style looks pretty good. I'd make these changes:
APP = (function() {
var _userId = -1;
var _privateVar = '';
var init = function($userId) {
_userId = $userId;
};
var publicMethod = function($id){
_privateVar = id;
};
return {
init : init,
publicMethod : _publicMethod
};
})();
First, underscores are generally meant to denote "private" properties or methods. Secondly, you can do away with the extra functions in the object being returned and just point straight to the methods or properties you care about. This is generally referred to as the "Revealing Module Pattern", because even the public methods aren't defined within the returned object - they're simply referenced.
3) This approach is definitely a nice way to encapsulate code. You get the benefit of private and privileged methods, and you generally end up with a nicer API because you're only exposing things that need to be public.
Well done.

Load "Vanilla" Javascript Libraries into Node.js

There are some third party Javascript libraries that have some functionality I would like to use in a Node.js server. (Specifically I want to use a QuadTree javascript library that I found.) But these libraries are just straightforward .js files and not "Node.js libraries".
As such, these libraries don't follow the exports.var_name syntax that Node.js expects for its modules. As far as I understand that means when you do module = require('module_name'); or module = require('./path/to/file.js'); you'll end up with a module with no publicly accessible functions, etc.
My question then is "How do I load an arbitrary javascript file into Node.js such that I can utilize its functionality without having to rewrite it so that it does do exports?"
I'm very new to Node.js so please let me know if there is some glaring hole in my understanding of how it works.
EDIT: Researching into things more and I now see that the module loading pattern that Node.js uses is actually part of a recently developed standard for loading Javascript libraries called CommonJS. It says this right on the module doc page for Node.js, but I missed that until now.
It may end up being that the answer to my question is "wait until your library's authors get around to writing a CommonJS interface or do it your damn self."
Here's what I think is the 'rightest' answer for this situation.
Say you have a script file called quadtree.js.
You should build a custom node_module that has this sort of directory structure...
./node_modules/quadtree/quadtree-lib/
./node_modules/quadtree/quadtree-lib/quadtree.js
./node_modules/quadtree/quadtree-lib/README
./node_modules/quadtree/quadtree-lib/some-other-crap.js
./node_modules/quadtree/index.js
Everything in your ./node_modules/quadtree/quadtree-lib/ directory are files from your 3rd party library.
Then your ./node_modules/quadtree/index.js file will just load that library from the filesystem and do the work of exporting things properly.
var fs = require('fs');
// Read and eval library
filedata = fs.readFileSync('./node_modules/quadtree/quadtree-lib/quadtree.js','utf8');
eval(filedata);
/* The quadtree.js file defines a class 'QuadTree' which is all we want to export */
exports.QuadTree = QuadTree
Now you can use your quadtree module like any other node module...
var qt = require('quadtree');
qt.QuadTree();
I like this method because there's no need to go changing any of the source code of your 3rd party library--so it's easier to maintain. All you need to do on upgrade is look at their source code and ensure that you are still exporting the proper objects.
There is a much better method than using eval: the vm module.
For example, here is my execfile module, which evaluates the script at path in either context or the global context:
var vm = require("vm");
var fs = require("fs");
module.exports = function(path, context) {
context = context || {};
var data = fs.readFileSync(path);
vm.runInNewContext(data, context, path);
return context;
}
And it can be used like this:
> var execfile = require("execfile");
> // `someGlobal` will be a global variable while the script runs
> var context = execfile("example.js", { someGlobal: 42 });
> // And `getSomeGlobal` defined in the script is available on `context`:
> context.getSomeGlobal()
42
> context.someGlobal = 16
> context.getSomeGlobal()
16
Where example.js contains:
function getSomeGlobal() {
return someGlobal;
}
The big advantage of this method is that you've got complete control over the global variables in the executed script: you can pass in custom globals (via context), and all the globals created by the script will be added to context. Debugging is also easier because syntax errors and the like will be reported with the correct file name.
The simplest way is: eval(require('fs').readFileSync('./path/to/file.js', 'utf8'));
This works great for testing in the interactive shell.
AFAIK, that is indeed how modules must be loaded.
However, instead of tacking all exported functions onto the exports object, you can also tack them onto this (what would otherwise be the global object).
So, if you want to keep the other libraries compatible, you can do this:
this.quadTree = function () {
// the function's code
};
or, when the external library already has its own namespace, e.g. jQuery (not that you can use that in a server-side environment):
this.jQuery = jQuery;
In a non-Node environment, this would resolve to the global object, thus making it a global variable... which it already was. So it shouldn't break anything.
Edit:
James Herdman has a nice writeup about node.js for beginners, which also mentions this.
I'm not sure if I'll actually end up using this because it's a rather hacky solution, but one way around this is to build a little mini-module importer like this...
In the file ./node_modules/vanilla.js:
var fs = require('fs');
exports.require = function(path,names_to_export) {
filedata = fs.readFileSync(path,'utf8');
eval(filedata);
exported_obj = {};
for (i in names_to_export) {
to_eval = 'exported_obj[names_to_export[i]] = '
+ names_to_export[i] + ';'
eval(to_eval);
}
return exported_obj;
}
Then when you want to use your library's functionality you'll need to manually choose which names to export.
So for a library like the file ./lib/mylibrary.js...
function Foo() { //Do something... }
biz = "Blah blah";
var bar = {'baz':'filler'};
When you want to use its functionality in your Node.js code...
var vanilla = require('vanilla');
var mylibrary = vanilla.require('./lib/mylibrary.js',['biz','Foo'])
mylibrary.Foo // <-- this is Foo()
mylibrary.biz // <-- this is "Blah blah"
mylibrary.bar // <-- this is undefined (because we didn't export it)
Don't know how well this would all work in practice though.
I was able to make it work by updating their script, very easily, simply adding module.exports = where appropriate...
For example, I took their file and I copied to './libs/apprise.js'. Then where it starts with
function apprise(string, args, callback){
I assigned the function to module.exports = thus:
module.exports = function(string, args, callback){
Thus I'm able to import the library into my code like this:
window.apprise = require('./libs/apprise.js');
And I was good to go. YMMV, this was with webpack.
A simple include(filename) function with better error messaging (stack, filename etc.) for eval, in case of errors:
var fs = require('fs');
// circumvent nodejs/v8 "bug":
// https://github.com/PythonJS/PythonJS/issues/111
// http://perfectionkills.com/global-eval-what-are-the-options/
// e.g. a "function test() {}" will be undefined, but "test = function() {}" will exist
var globalEval = (function() {
var isIndirectEvalGlobal = (function(original, Object) {
try {
// Does `Object` resolve to a local variable, or to a global, built-in `Object`,
// reference to which we passed as a first argument?
return (1, eval)('Object') === original;
} catch (err) {
// if indirect eval errors out (as allowed per ES3), then just bail out with `false`
return false;
}
})(Object, 123);
if (isIndirectEvalGlobal) {
// if indirect eval executes code globally, use it
return function(expression) {
return (1, eval)(expression);
};
} else if (typeof window.execScript !== 'undefined') {
// if `window.execScript exists`, use it
return function(expression) {
return window.execScript(expression);
};
}
// otherwise, globalEval is `undefined` since nothing is returned
})();
function include(filename) {
file_contents = fs.readFileSync(filename, "utf8");
try {
//console.log(file_contents);
globalEval(file_contents);
} catch (e) {
e.fileName = filename;
keys = ["columnNumber", "fileName", "lineNumber", "message", "name", "stack"]
for (key in keys) {
k = keys[key];
console.log(k, " = ", e[k])
}
fo = e;
//throw new Error("include failed");
}
}
But it even gets dirtier with nodejs: you need to specify this:
export NODE_MODULE_CONTEXTS=1
nodejs tmp.js
Otherwise you cannot use global variables in files included with include(...).

Categories