What is a circular dependency in Node.js and what happens when it occurs?
A circular dependency is when module A requires B and B requires A. In CommonJS, the second module receives A's partially filled exports at that moment, so values defined later are undefined. Fix it by restructuring.
Explain it simply
Two friends each say, "I will give you my notes once you give me yours." Neither can finish first. Node does not freeze; it hands over whatever the other person has written so far, which may be half-empty.
When a.js requires b.js and b.js requires a.js again, Node sees that a.js is still running. It returns the current, incomplete module.exports of a.js instead of waiting.
Example
// a.js
exports.loaded = false;
const b = require("./b");
exports.loaded = true;
console.log("in a, b.sawA =", b.sawA); // prints: in a, b.sawA = false
// b.js
const a = require("./a");
exports.sawA = a.loaded; // a.loaded is still false hereNo error is thrown, which is why this bug is nasty: you just get undefined or stale values.
How to avoid it:
- Move the shared code into a third module that both files require.
- Require lazily inside the function that needs it, not at the top.
- Pass dependencies as function arguments.
What to say in the interview
"With CommonJS, a cycle returns the partially completed exports of the module that is still loading, so some properties are missing. I would break the cycle by extracting shared logic into a third module or requiring inside the function."
Common mistakes
- Assuming Node throws an error for cycles.
- Using
module.exports = ...after the cyclic require; the other module keeps the old object.