Circular dependencies in node.js
You required a module and got {}
instead. What happened ? How to avoid it ?
If you've been writing node.js code for a while, you've definitely ran into this one. If not, here's a quick example: https://gist.github.com/lperrin/5934098
You have 3 modules requiring each other: A -> B -> C -> A. When you run node main.js
, you get:
moduleA.hello();
^
TypeError: Object #<Object> has no method 'hello'
Although A clearly defines the method. If you investigate more, you'll see that A is replaced by an empty object. You can go deeper by running: NODE_DEBUG=module node main.js
and trace how modules are loaded.
Basically:
- A starts loading and requires B.
- B requires C.
- C requires A.
A this point, A is already in the require cache, but is only an empty object. This shouldn't be a problem, since A has finished loading when we run our code.
However, here we use module.exports = …
. Because of this, C keeps a reference to an object that is no longer used and never gets the real module.
You can solve this easily: just export your data before you require anything else in modules where you use module.exports
:
function ModuleA() {
}
module.exports = ModuleA;
var moduleB = require('./b');
ModuleA.hello = function () {
console.log('hello!');
};
Written by Laurent Perrin
Related protips
6 Responses
Brilliant, thank you for the pro-tip. Saved me unnecessarily refactoring my code.
"Because of this, C keeps a reference to an object that is now longer used and never gets the real module." Typo? now should be no? as in "no longer used" ?
Seriously. Bravo.
Wow, thank you!!
thanks very much <3
Thanks a lot. I have converted your code to ES6
.
https://github.com/tomalex0/node-circular-dependcy