AlbertEngelB
AlbertEngelB

Reputation: 16456

Requiring Singleton Instances in Node

I spied in some code the following:

var Log = require('log');

// This creates a singleton instance
module.exports = new Log('info');

My first reaction was "no way that is a singleton", but I remember an article that outlined how Node.js does require() statements said something about caching require statements and using them in subsequent calls.

So basically my question, is exporting a new Object() actually creating a singleton behind the scenes?

I know there are other ways of creating singletons in JavaScript, but this seems like a pretty handy way of doing it inside Node (if it actually works).

Upvotes: 1

Views: 635

Answers (3)

Mario
Mario

Reputation: 3313

Yes, that's the closest thing to a Singleton in Node.js. require() caches each module upon the first invocation, so every subsequent require() returns always the same instance.

However you must be aware that this is not always enforced. The cache could be modified/removed, also the module is cached using its fullpath, in short it means that if you define a singleton in a package and your package is installed as nested dependency, you may have several instances of your "singleton" within the context of the same application. Quick example:

Application
  node_modules
    PackageA
      node_modules
        YourPackageWithSingleton
    PackageB
      node_modules
        YourPackageWithSingleton

Usually you don't have to worry about this, but if you really need to share one object across the entire application, the only solution is using globals (discouraged) or Dependency Injection.

Upvotes: 3

Aadit M Shah
Aadit M Shah

Reputation: 74234

Why not test it out for yourself?

$ cat test.js
module.exports = Math.random();
$ node
> var a = require("./test");
undefined
> var a = require("./test");
undefined
> a === b
true

Yes, it seems that node.js does indeed cache exported values. Hence if you require the same module again it will return the cached value instead of creating a new value.

It should be noted however that the programmer could just require("log") and create a new instance manually. So in that sense it is not a singleton.

Upvotes: 1

dsuckau
dsuckau

Reputation: 592

Its not really a singleton due to you could create as much instances of Log as you want. But you can use it like this. Otherwise you just can create an plain object by var mySingleton = {} and attach attributes and methods to it.

Then you can assign mySingleton to module.exports and require() it in other modules.

foo.js:

var mySingleton = {
    someMethod = function () {}
};

module.exports = mySingleton;

bar.js:

var singletonClass = require('./foo.js');

singletonClass.someMethod();

Upvotes: 1

Related Questions