Reputation: 1509
I have a custom module called counter, which is used by multiple other modules. These other modules are located in different directories, which leads to requiring the counter module with different paths.
Below is simplified setup.
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
counter.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('./counter');
counter.increment(); // Prints 1
module2.js
var counter = require('../dir1/counter')
counter.increment(); // Prints 1, but should print 2
If the same include path was used, then counter would only be created once and the same counter module would be used by both module1 and module2. But because the require paths are different, two separate counter modules are created.
Does anyone know how to prevent this? I would like to have only one counter module.
Upvotes: 1
Views: 354
Reputation: 545
This happens because when you import a file, it creates a new instance there, so in every module of yours it will start with 0.
Solution would be to import counter as global in main file and use the same everywhere
In main file
global.counter = require('./counter');
in module files
global.counter.increment();
counter file can be loaded from any of the files, modules and it won't matter. Just declare it once and make sure it is loaded before using the increment method.
Upvotes: 0
Reputation: 952
I use NODE_PATH
environment variable in my projects. It's value is, root of the project. Then requiring local modules becomes like requiring npm
modules.
For your same setup, I change the require statements:
Below is simplified setup.
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
exports.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('dir1/counter');
counter.increment(); // Prints 1
module2.js
var counter = require('dir1/counter')
counter.increment(); // Prints 2
I run the program with NODE_ENV
environment variable.
NODE_ENV=. node
> require('dir1/module1');
1
{}
> require('dir2/module2');
2
{}
>
.
indicates, current folder.
Upvotes: 0
Reputation: 265
A good solution would be to make only the count variable global instead of making the complete module global. For Example-
In Main File-
global.count=0;
In counter.js
counter.increment = function(){
count++;
console.log(count);
};
This way you don't need to change your module1.js and module2.js and even for further modules you can use it as you would have earlier.
Upvotes: 1
Reputation: 707198
Since you want a per-app singleton and require()
has no way of knowing that a module with two separate paths is actually the same module, the only way I know of to do this (other than removing the separate paths to the module) is to have your module register a singleton as a global and then have it's own initialization check for that singleton before creating another singleton. Then, each time you load it, it would just return an export that points to that one singleton.
// counter.js
// if no singleton yet, create the one singleton
if (!global._counter) {
global._counter = new Counter();
}
// export the singleton
module.exports = global._counter;
The first time this is loaded with require()
(no matter what the path), it will create the one singleton and store it in the global._counter
variable. The second time it is loaded (even with a different path), it will find the previous singleton and just export that same one. So, there will only ever be one counter.
This lets all the code that is using it treat it like a real module and avoid using global
references anywhere but here. Using globals is generally to be avoided, but this is one thing they are good for when you want a singleton reference to something and cannot use a module-level variable to hold it (which is your exact case).
Then, you can just use it like a normal module:
var counter = require('./counter');
counter.increment(); // Prints 1
// in another file
var counter = require('../dir1/counter');
counter.increment(); // Prints 2
Upvotes: 2