Reputation: 555
To break it down and simplify it a bit: Imagine I have three files in my project. One main.js, and two modules: moduleA.js and moduleB.js. main.js accesses moduleA.js which calls a function from moduleB.js. Now moduleB.js finds out that it needs an information that is only available in moduleA.js. Of course moduleB.js tries to access a function in moduleA.js which is technically able to give this information to moduleB.js but there is an error.
Here is the simplified code.
main.js
var a = require("./moduleA.js");
console.log(a.respond());
moduleA.js
var b = require("./moduleB.js");
module.exports = {
respond: function(){
return b.returnAnswerForModuleA();
},
getSomeInformationOnlyAvailableInA: function(){
return "This is the information we need!";
}
};
moduleB.js
var a = require("./moduleA.js");
module.exports = {
returnAnswerForModuleA: function(){
return a.getSomeInformationOnlyAvailableInA()
}
};
Here is the error message:
/Users/Tim/Code/ChatBot/test/moduleB.js:5
return a.getSomeInformationOnlyAvailableInA()
^
TypeError: a.getSomeInformationOnlyAvailableInA is not a function
at Object.module.exports.returnAnswerForModuleA (/Users/Tim/Code/ChatBot/test/moduleB.js:5:16)
at Object.module.exports.respond (/Users/Tim/Code/ChatBot/test/moduleA.js:5:18)
at Object.<anonymous> (/Users/Tim/Code/ChatBot/test/main.js:3:15)
at Module._compile (module.js:425:26)
at Object.Module._extensions..js (module.js:432:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Function.Module.runMain (module.js:457:10)
at startup (node.js:136:18)
at node.js:972:3
Why cannot I access moduleA.js from moduleB.js?
To restructure my code is not really an option!
Thanks for help!
Upvotes: 1
Views: 198
Reputation: 708176
This looks like an issue with circular dependencies in node.js where a circular dependency causes one module to be resolved as an empty object (thus causing the error you see). See these articles which explain:
Node.js and circular dependencies
Circular dependencies in Node.js
The first article offers two possible solutions: "delaying invocation of dependency until runtime" and "replace circular dependency with dependency injection".
I think you can work around the circular issue by changing module B to this:
var moduleA;
module.exports = {
returnAnswerForModuleA: function(){
if (!moduleA) {
moduleA = require("./moduleA.js");
}
return moduleA.getSomeInformationOnlyAvailableInA()
}
};
This delays the loading of module A in module B until runtime by which time, it is already successfully loaded and in the module cache, thus avoiding the circular dependency.
Upvotes: 2