Nam Nguyen
Nam Nguyen

Reputation: 5750

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

Upvotes: 6

Views: 6388

Answers (3)

Eric Elliott
Eric Elliott

Reputation: 4751

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.

Upvotes: 10

tusharmath
tusharmath

Reputation: 10992

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!

Upvotes: 0

Andrew Eisenberg
Andrew Eisenberg

Reputation: 28747

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,

Upvotes: 4

Related Questions