Ronin
Ronin

Reputation: 1693

Why so strange behaviour when using "require" in NodeJS?

When I import ClassA inside ClassB, and then import ClassA inside ClassB, the imported ClassA is an empty Object. To demonstrate, I have these 3 files:

ClassA.js

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

class ClassA {
    static test() {
        ClassB.test();
    }
}

module.exports = ClassA;

ClassB.js

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

class ClassB {
    static test() {
        console.log('ClassA.test', ClassA.test);
    }
}

module.exports = ClassB;

index.js

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

ClassA.test();

When I run node index.js, I expect to see ClassA.test function in console, but it outputs ClassA.test undefined instead. Is it some undocumented thing, or it's a bug?

Upvotes: 0

Views: 58

Answers (2)

Marcos Casagrande
Marcos Casagrande

Reputation: 40404

You have a circular dependency. The solution is to have a third class that will require both and use whatever code you have from ClassA in ClassB and the other way around.

const ClassA = require('./ClassA');
const ClassB = require('./ClassB');

class ClassC {
    static test() {
        ClassA.test();
        ClassB.test();
    }
}

When I run node index.js, I expect to see ClassA.test function in console, but it outputs ClassA.test undefined instead. Is it some undocumented thing, or it's a bug?

No, it's not a bug, and it's not undocumented.

You can read more here on how it's handled: https://nodejs.org/api/modules.html#modules_cycles


You can also do a lazy load, and will solve your issues for this particular case. But in most cases, circular references are a symptom of poorly written code.

class ClassB {
    static test() {
        const ClassA = require('./ClassA')
        console.log('ClassA.test', ClassA.test);
    }
}

module.exports = ClassB;

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370699

You have a circular dependency, so Node can't know for certain which module's top-level code should run first - one of the modules needs to have its top-level code run first so that something should be exported so that the other module can import it via require. But if both depend on the other, then the first one that runs will have its require call to the other resolve to undefined.

The best solution would be to refactor it to avoid the circular dependency.

Upvotes: 1

Related Questions