4

I have one module which wraps the Socket.io functionality my app is using which looks something like this:

// realtime.js
var io = require('socket.io'),
    sio;

exports.init = function(expressServer) {
    sio = io.listen(expressServer);
}

...

The main app.js file looks like

// app.js
var rt = require('./realtime.js'),
    other = require('./other.js');
...
rt.init(expressServer);

The other module also uses rt.js

// other.js
var rt = require('./realtime.js');
...

My question is, will both other.js and app.js have the same instance of rt.js?

The answer on SO relating to redis lead me to believe the above statement is true, but in the documentation here it says

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.

which seems to imply that it's not guaranteed to be the case?

Finally this question appears to indicate it depends on filename and that since there is only one instance of rt.js it shouldn't be executed more than once. If that's the case does it depend only on rt.js being the same file or does it depend on the path specified by require. Basically if rt.js and other.js were in lib/, and app.js was one level down the requires in other.js and app.js would point to rt.js from different files, does this matter?

I'd be grateful if anyone could clear this confusion up for me!

Community
  • 1
  • 1
Bob Smith
  • 791
  • 2
  • 9
  • 19
  • why are you calling require in both js files - what's preventing you from passing the reference to the module from app.js? – ali haider Jul 18 '12 at 15:40
  • I haven't been able to think of a clean way to do that without making a lot of changes to the code (using require it doesn't seem to mater if two modules that app.js requires also require each other, where as changing that setup would take a while). I'm all for it if that's what's going to be required, but I'm also just curious about how this works :). Thanks for your comment! – Bob Smith Jul 18 '12 at 15:59
  • ok - normally, if I have a reference to something (for instance, redis), I pass that reference in the call to the module. hope it helps – ali haider Jul 18 '12 at 16:02
  • 1
    Google "javascript modules singleton pattern" and I believe you will find easy to implement solutions that allow you to require the module multiple times, but each time returning the same instance when relevant. – Marius Kjeldahl Jul 18 '12 at 16:03

2 Answers2

5

modules are currently evaluated only once, but you should not rely on this. Having any state in module is considered bad practice. What prevents you from passing reference to sio to other.js?

//realtime
var io = require('socket.io'),

exports.init = function(expressServer) {
    return io.listen(expressServer);
}

// app.js
var rt = require('./realtime.js'),
    other = require('./other.js');
...
var sio = rt.init(expressServer);
// now ask other.js to use same sio instance
other.use_sio(sio);
Andrey Sidorov
  • 24,905
  • 4
  • 62
  • 75
0

Be sure not to install socket.io in more than one place. If you require socket.io in different modules where each module is searching for packages from different paths, then each module will load a seperate instance of the package.

app directory layout:

-module1
--/npm_modules //has socket.io
---/socket.io
--/module1.js //requires socket.io from module1/npm_modules

-module2
--/npm_modules //has another socket.io installation
---/socket.io
--/module2.js //requires socket.io from module2/npm_modules (Does not create a reference to what was required in module1.)

Hope this helps.