Question

I'm creating a node.js project following the class constructor pattern:

function my_class(x,y){
    this.x = x;
    this.y = y;
}

The starting point of the project is the main.js file. Any class of the project must be able to access global objects (such as "world" and "socket") which are defined on main.js. I found 4 options:

  1. I define my classes inside main.js. They'll have access to main.js's globals for being on it's closure, but main.js will become bloated.

  2. I move the class to another file such as my_class.js and require() it. This doesn't work because my_class's instances will lose the closure context and no longer be able to access main.js's globals.

  3. I move the class to another file and manually inject dependencies to it's constructor (ex: my_class(world,socket)). The problem is, code becomes much more complicated and weird semantics such as "my_instance.world" pop on the source, which is nonsense because "world" is not property of my_class.

  4. I move the class to another file and require it using my_class = eval(fs.readFileSync(()) instead of require. This works just fine as my_class gets main.js's closure context, and is the solution I'm using, but seems hacky.

Which is the right way to modularize such node.js project?

Was it helpful?

Solution 2

Your problem seems tricky because you have a circular dependency: main.js depends on the functionality of my_class and my_class depends on the data of main.js.

By putting the data of main.js into the global object you resolve the circular dependency:

  • main.js depends on the functionality of my_class.js
  • main.js depends on the data in the global object
  • my_class.js depends on the data in the global object

Now, to get rid of putting the data into the global object, implement a third module in let us say data.js. Then you require the sources like this:

  • main.js requires data.js
  • main.js requires my_class.js
  • my_class.js requires data.js

Since modules in node.js are singletons both main.js and my_class.js will get the same instance of data.js.

OTHER TIPS

If I understood you correctly the possible solution:

main.js:

(function(){
  var global = "test"; // this you wanna have as a closure

  var my_class = require('./my_class')(global);
  my_class.go();
})();

my_class.js:

module.exports = function(global){
  return {
    go: function(){
      console.log(global);
    }
  };
};

So it's similar to your 3. option

If you want to make variables in main.js available anywhere, then you can assign properties to the global object. See node.js global variables? for example. It would work fine as long as you don't over do it. With Neo's solution, you gain a little more flexibility for example with testing, because you can "inject" an arbitrary object into the module. Not every module has to use the same "global" per se.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top