I have a problem with circular dependencies when doing module.exports = <ClassName>.
Here is an example. ClassC requires ClassB, ClassB requires ClassA, ClassA requires ClassC. And in main.js we just create a new instance of ClassC and call the method, that will do a chain of calls:
/* classA.js */
'use strict';
const ClassC = require('./classC.js');
class ClassA {
foo() {
console.log('ClassA.foo');
var classC = new ClassC();
classC.bar();
}
}
module.exports = ClassA;
/* classB.js */
'use strict';
const ClassA = require('./classA.js');
class ClassB {
foo() {
console.log('ClassB.foo');
var classA = new ClassA();
classA.foo();
}
}
module.exports = ClassB;
/* classC.js */
'use strict';
const ClassB = require('./classB.js');
class ClassC {
foo() {
console.log('ClassC.foo');
var classB = new ClassB();
classB.foo();
}
bar() {
console.log('ClassC.bar');
}
}
module.exports = ClassC;
/* main.js */
'use strict';
const ClassC = require('./classC.js');
var classC = new ClassC();
classC.foo();
So when I do call node main.js i get an obvious error that ClassC is not resolved.
D:\Projects\test-circular-reference-es6\classA.js:8
var classC = new ClassC();
^
TypeError: ClassC is not a function
at ClassA.foo (D:\Projects\test-circular-reference-es6\classA.js:8:22)
at ClassB.foo (D:\Projects\test-circular-reference-es6\classB.js:9:16)
at ClassC.foo (D:\Projects\test-circular-reference-es6\classC.js:9:16)
at Object.<anonymous> (D:\Projects\test-circular-reference-es6\main.js:7:8)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
This happens because when ClassC was required in ClassA it was still a process of ClassC loading, so an empty object was returned and later at the end of classC.js the module.exports was overwritten with ClassC while that reference to empty object in classA.js remained as it was.
So the question is how to deal with this, what is the best practice to have both circular references and exporting classes in NodeJS 4.x (ES6)?
From my side I see the following possible ways:
- Do not overwrite module.exports and do something like
module.exports.class = ClassC;
and then instantiate likenew ClassC.class();
But this also introduces more difficulties for inheritance and clumsy code in general. - Use TypeScript instead, because it will handle this stuff.
Any suggestions are welcome.