How to deal with cyclic dependencies in Node.js
I've been working with nodejs lately and still getting to grips with the module system so apologies if this is an obvious question. I want code roughly like the following below:
a.js (the main file run with node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var a = require("./a");
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
My problem seems to be that I can't access the instance of ClassA from within an instance of ClassB.
Is there a correct / better way to structure modules to achieve what I want? Is there a better way to share variables between modules?
Try to set properties on module.exports
, instead of replacing it completely. E.g., module.exports.instance = new ClassA()
in a.js
, module.exports.ClassB = ClassB
in b.js
. When you make circular module dependencies, the requiring module will get a reference to an incomplete module.exports
from the required module, which you can add other properties latter on, but when you set the entire module.exports
, you actually create a new object which the requiring module has no way to access.
While node.js does allow circular require
dependencies, as you've found it can be pretty messy and you're probably better off restructuring your code to not need it. Maybe create a third class that uses the other two to accomplish what you need.
[EDIT] it's not 2015 and most libraries (i.e. express) have made updates with better patterns so circular dependencies are no longer necessary. I recommend simply not using them.
I know I'm digging up an old answer here... The issue here is that module.exports is defined after you require ClassB. (which JohnnyHK's link shows) Circular dependencies work great in Node, they're just defined synchronously. When used properly, they actually solve a lot of common node issues (like accessing express.js
app
from other files)
Just make sure your necessary exports are defined before you require a file with a circular dependency.
This will break:
var ClassA = function(){};
var ClassB = require('classB'); //will require ClassA, which has no exports yet
module.exports = ClassA;
This will work:
var ClassA = module.exports = function(){};
var ClassB = require('classB');
I use this pattern all the time for accessing the express.js app
in other files:
var express = require('express');
var app = module.exports = express();
// load in other dependencies, which can now require this file and use app