Circular Dependencies causing empty Object for required module


#1

I have three packages that I am trying to call functions between.
Connector has a require for Tree and Settings, this works as expected and I can call functions.
Tree has a require for Settings.
However when I add Tree to be required in my Settings module the Connector module shows the Tree object as {} instead of the actual instance of the module.

Why would adding tree as a dependency for Settings and Connector break the pattern?

Connector--> Settings
Connector--> Tree
Tree--> Settings
Tree--> Connector
Adding this last one breaks it
Settings--> Tree


#2

@leedohm any thoughts on this?


#3

So:

Connector --> Settings --> Tree
         \---------------> Tree

I don’t see anything circular about this pattern.

But, without being able to see the actual code, I can only guess at what the issue might be. Here are some thoughts:

The Tree module creates an object and returns it as its module.exports. Whatever requires Tree the first time, empties out that object … somehow. To my understanding, Node caches required exports so that successive requires don’t have to parse the file over and over again, but that wouldn’t prevent the requirer from mucking about with them, I don’t think.

Other than that, I’ve got nothing sadly … I thought I would have more :frowning:


#4

I forgot to mention that Tree has a require on Settings.


#5

Maybe your problem is a (slightly more complex) version of the following:

tree.js:

// will execute the contents of settings.js
// module.exports is still an empty object at this point
var Settings = require('settings.js');

// change module.exports here

settings.js:

// tree.js has already been required before (in connector.js), so use
// the cached value of tree.js's module.exports, which is still empty
var Tree = require('tree.js');

// change module.exports here

// the Tree object is still empty, because settings.js
// hasn't finished executing yet
Tree.doStuff(); // Error: Object.doStuff is not a function

// change module.exports here

This page in the node docs also explains it nicely.

You can try to fix this by changing the order in which files are required, or by exporting some (or all) functions before requiring the other file, but I wouldn’t go down that road because it adds complexity to your program that isn’t immediately obvious, especially with more than 1 circular dependency within the same set of files. If someone (accidentally) switched the order in which settings.js and tree.js are required in connector.js, things might stop working all of a sudden… A better solution would be to rework the program so that no functions from tree.js are called in the body of settings.js.