Tim Visée Tim Visée - 1 year ago 42
Node.js Question

NodeJS: Early require doesn't have access to object field

I'm having a problem accessing a field in an object that is required/imported at the top of a file, the field is accessible however when importing the object again at a later point in the code.

I've made a little example to show what I mean: [Execute code on CodingGround]


var ClassA = require('./ClassA');



var ClassB = require('./ClassB');

var ClassA = function() {};

ClassA.init = function() {
// Define a variable in ClassA
this.myVar = 'My Value';

// Create an instance of ClassB, and try to print the defined variable
var myClass = new ClassB();

module.exports = ClassA;


var ClassA = require('./ClassA');

var ClassB = function() {};

ClassB.prototype.printMyVar = function() {
// Print the variable (not working)
console.log('My Var: ' + ClassA.myVar);

// Require ClassA again
ClassA = require('./ClassA');

// Print the variable again (working)
console.log('My Var (again): ' + ClassA.myVar);

module.exports = ClassB;

I get the following output when
is executed:

My Var: undefined
My Var (again): My Value

Why does the first line show the variable is undefined, and why does it show the variable properly after requiring/importing the object again?

Is this caused by a circular dependency and if so, how can I avoid this problem in the future?

Answer Source

This is the situation described in the NodeJS modules "cycle" topic. The solution seems to be to augment the exports object rather than replacing it if circular dependencies are present.

Here's their example, modified to show that when b checks a.done later, it sees the correct value:


console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');


console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
exports.check = function() {
    console.log('in b\'s check function, a.done = %j', a.done);
console.log('b done');


console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);

The output is:

main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true
in b's check function, a.done = true