I keep getting this issue in Node where my application crashes whenever I'm calling functions from one another.
I've made this minimum working example (working as in it gives me the error):
Start module
var module2 = require('./module2');
var data = 'data';
module2.doStuff(data);
Module2
var module3 = require('./module3');
function doStuff(data){
// Stuff happens to 'data'
module3.takeStuff(data);
}
function doSomethingElse(data){
console.log(data);
}
module.exports = {
doStuff: doStuff,
doSomethingElse: doSomethingElse
};
Module3
var module2 = require('./module2');
function takeStuff(data){
// Stuff happens to 'data'
module2.doSomethingElse(data); // I get the type error here
}
module.exports = {
takeStuff: takeStuff
};
The error I get is:
module2.doSomethingElse(data); // I get the type error here
^
TypeError: undefined is not a function
The start module
calls a function in module2
which ultimately calls for a function in module3
, which in turn calls for a function in module2
.
All modules are properly required and it finds the first method in module2
just fine.
What's happening here and how would one go about this pattern when one needs to get a function from the module one came with?
EDIT
Debugging shows me that the module exists, but it's empty apart from the prototype it has. My question is why? Inside of Node/JavaScript, what's happening here?
I keep getting this issue in Node where my application crashes whenever I'm calling functions from one another.
I've made this minimum working example (working as in it gives me the error):
Start module
var module2 = require('./module2');
var data = 'data';
module2.doStuff(data);
Module2
var module3 = require('./module3');
function doStuff(data){
// Stuff happens to 'data'
module3.takeStuff(data);
}
function doSomethingElse(data){
console.log(data);
}
module.exports = {
doStuff: doStuff,
doSomethingElse: doSomethingElse
};
Module3
var module2 = require('./module2');
function takeStuff(data){
// Stuff happens to 'data'
module2.doSomethingElse(data); // I get the type error here
}
module.exports = {
takeStuff: takeStuff
};
The error I get is:
module2.doSomethingElse(data); // I get the type error here
^
TypeError: undefined is not a function
The start module
calls a function in module2
which ultimately calls for a function in module3
, which in turn calls for a function in module2
.
All modules are properly required and it finds the first method in module2
just fine.
What's happening here and how would one go about this pattern when one needs to get a function from the module one came with?
EDIT
Debugging shows me that the module exists, but it's empty apart from the prototype it has. My question is why? Inside of Node/JavaScript, what's happening here?
This issue here can be easily fixed, while keeping the structure of your app (which is fine, in regard to circular references).
You just need need to keep the default exports
object that is given to your modules by the system. Do not change it with module.exports = {...}
.
The following should work:
var module2 = require('./module2');
var data = 'data';
module2.doStuff(data);
var module3 = require('./module3');
exports.doStuff = function doStuff(data){
// Stuff happens to 'data'
module3.takeStuff(data);
};
exports.doSomethingElse = function doSomethingElse(data){
console.log(data);
};
var module2 = require('./module2');
exports.takeStuff = function takeStuff(data){
// Stuff happens to 'data'
module2.doSomethingElse(data); // I get the type error here
};
I'll try to explain what happens from the first line of your starting point:
module.exports = {...}
module.exports = {...}
The issue here is between points 3 and 6. Module3 is receiving the exports of module2 (3) before you change the reference to it (6).
Using exports.method = ...
solves the problem because the exports object never changes.
You've got a circular reference, module 2 depends on module 3 which depends on module 2 which depends on module 3 (and so on). So while trying to resolve module 3
for module 2
, it cannot plete it because module 3
itself needs to be resolved first.
From https://nodejs/api/modules.html#modules_cycles:
When there are circular require() calls, a module might not have finished executing when it is returned.
In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module.
So the module is available, but inplete (which explains that you only receive a prototype). Circular references are a code smell anyway, try to avoid it :)
However, if you put both module 2 and 3 as a dependency in your starting module, it should work anyway.
var module2 = require('./module2');
var module3 = require('./module3');
var data = 'data';
module2.doStuff(data);