Last Updated: October 07, 2017
·
28.62K
· lperrin

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!');
};

6 Responses
Add your response

Brilliant, thank you for the pro-tip. Saved me unnecessarily refactoring my code.

over 1 year ago ·

"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" ?

over 1 year ago ·

Seriously. Bravo.

over 1 year ago ·

Wow, thank you!!

over 1 year ago ·

thanks very much <3

over 1 year ago ·

Thanks a lot. I have converted your code to ES6.
https://github.com/tomalex0/node-circular-dependcy

over 1 year ago ·