Node and Cyclic Dependencies
11/11/15
I feel like I've come into a rite of passage in JavaScript. I have hit the classical circular dependencies problem.
What I have is a script called
publish,
it requires
htmlGenerate,
template,
and
database.
All also scripts I have made.
htmlGenerate
translates my bare-bones blog files into published posts,
template
is a basic script I made to fill in template html files I have (will
soon be replaced by a proper library made by someone else),
and
database
is my wrapper for interacting with my textfile lists that say what
posts are published to index and in what order (hopefully eventually
it'll refer to a proper database).
The order I mentioned these requirements are important, because requirements are loaded in order, so....
In
htmlGenerate,
rssGenerate
is required, and in there
database
is required, and in there
rssGenerate
is required.
And there's the circular dependency.
rssGenerate
to
database
and then back to
rssGenerate.
So, why does this matter? Because, as it turns out, when JavaScript A requires JavaScript B, and B also requires A, then B will only get A loaded up to the point where B is required.
Let me show you:
Let's make an A.js
// A.js
B = require('./B')
exports.afterB = true;
console.log('B after A:', B.afterA);
Now a B.js.
// B.js
A = require('./A')
exports.afterA = true;
console.log('A after B:', A.afterB);
And now a main.
// main.js
A = require('./A')
B = require('./B')
console.log('A after B:', A.afterB);
console.log('B after A:', B.afterA);
What happens when I run this code?
A after B: undefined
B after A: true
A after B: true
B after A: true
That "A after B" that gets logged in
B.js
is undefined. Why? A has required B, but B required A. A needs B to
be finished loaded before it can finish loading, so B gets an
incomplete copy of A and anything it does while initializing it does
with only what A had already load up until A required B.
And I hit this bug naturally with my code. Which tells me two things, 1) I'm getting more familiar with JavaScript, because I was able to cause this, and 2) I'm writing bad JavaScript, because I allowed this to happen.
That's okay, I'm working on it, and it's kinda fun that I found such an infuriating feature of node's require module.
Further Reading
Node's module documentation about cycles, complete with better example.