Avoiding circular dependencies with Node require()?

Tags: , , , ,



I’m having a problem where I have an Electron app, we’ll say contained in files index.html and app.js. app.js is included in index.html with a script tag.

Within app.js, I use var ENGINE = require("./myGameEngine/"); which then requires different classes, each in their own file. It looks something like this:

var myEngine = myEngine || {};
myEngine.ClassA = require('./src/ClassA');
myEngine.ClassB = require('./src/ClassB');
myEngine.ClassC = require('./src/ClassC');
module.exports = myEngine;

Unfortunately, sometimes ClassA, needs to use new myEngine.ClassB(). For example, if ClassA is an entity and has the function ClassA.addComponent() that function might require the use of var component = new myEngine.ClassB().

When trying to do this, I run into an error that myEngine is undefined, even though it’s the parent that required all these other files. I don’t want to require it back in ClassB as that will create a circular dependency, but I need ClassB inside ClassA sometimes.

What’s most infuriating is that previously, instead of including app.js with script tags and requiring myEngine with require() I simply required both myEngine.js and app.js from the HTML file, and that all worked fine.

I could go back to that system but I liked the simplicity of including a single JS file to go with my single HTML file, and doing all the requiring of the game engine inside that JS file, alongside modules from node_modules.

Can someone explain to me how what the problem is here and how I can require files within a module, without having to redefine the module in every file?

Thank you in advance!

Edit 1: Regarding suggestions to include the classes within other classes, I have created a drawing about why I’d like to avoid that: Can of Worms

Edit 2: Although I could require every class in every other class, there is is the issue of needing to access the parent module’s variables (that’s the main issue that caused me to write this, since I didn’t want to require the parent in the child and the child in the parent).

To be specific about that, consider this case:

myEngine.Entity = require('./src/Entity.js');
myEngine.Component = require('./src/Component.js');
myEngine.System = require('./src/System.js');

System.js has a method called update() which looks roughly like:

update: function(){
  for (let i = 0; i < myEngine.entities.length; i++) {
    doSomeLogic( myEngine.entities[i] );
  }
}

This did work when I used the script tags to include myEngine in the app, and no longer works when I include myEngine as a Node module. That’s sort of the crux of my frustration.

Answer

I’ve found an answer for myself.

By using myEngine = module.parent.exports in my sub classes, I can access not only the other classes (as long as the class doesn’t use the sub class until after the other class has been included in the parent’s module.exports), but also access higher scope variables like myEngine.entities.



Source: stackoverflow