How to deal with cyclic dependencies in Node.js

后端 未结 13 1964
别那么骄傲
别那么骄傲 2020-11-22 04:36

I\'ve been working with nodejs lately and still getting to grips with the module system so apologies if this is an obvious question. I want code roughly like the following b

相关标签:
13条回答
  • 2020-11-22 05:07

    Here is a quick workaround that I've found use full.

    On file 'a.js'

    let B;
    class A{
      constructor(){
        process.nextTick(()=>{
          B = require('./b')
        })
      } 
    }
    module.exports = new A();
    

    On the file 'b.js' write the following

    let A;
    class B{
      constructor(){
        process.nextTick(()=>{
          A = require('./a')
        })
      } 
    }
    module.exports = new B();
    

    This way on the next iteration of the event loop classes will be defined correctly and those require statements will work as expected.

    0 讨论(0)
  • 2020-11-22 05:10

    [EDIT] it's not 2015 and most libraries (i.e. express) have made updates with better patterns so circular dependencies are no longer necessary. I recommend simply not using them.


    I know I'm digging up an old answer here... The issue here is that module.exports is defined after you require ClassB. (which JohnnyHK's link shows) Circular dependencies work great in Node, they're just defined synchronously. When used properly, they actually solve a lot of common node issues (like accessing express.js app from other files)

    Just make sure your necessary exports are defined before you require a file with a circular dependency.

    This will break:

    var ClassA = function(){};
    var ClassB = require('classB'); //will require ClassA, which has no exports yet
    
    module.exports = ClassA;
    

    This will work:

    var ClassA = module.exports = function(){};
    var ClassB = require('classB');
    

    I use this pattern all the time for accessing the express.js app in other files:

    var express = require('express');
    var app = module.exports = express();
    // load in other dependencies, which can now require this file and use app
    
    0 讨论(0)
  • 2020-11-22 05:11

    An other method I've seen people do is exporting at the first line and saving it as a local variable like this:

    let self = module.exports = {};
    
    const a = require('./a');
    
    // Exporting the necessary functions
    self.func = function() { ... }
    

    I tend to use this method, do you know about any downsides of it?

    0 讨论(0)
  • 2020-11-22 05:14

    While node.js does allow circular require dependencies, as you've found it can be pretty messy and you're probably better off restructuring your code to not need it. Maybe create a third class that uses the other two to accomplish what you need.

    0 讨论(0)
  • 2020-11-22 05:14

    The solution is to 'forward declare' your exports object before requiring any other controller. So if you structure all your modules like this and you won't run into any issues like that:

    // Module exports forward declaration:
    module.exports = {
    
    };
    
    // Controllers:
    var other_module = require('./other_module');
    
    // Functions:
    var foo = function () {
    
    };
    
    // Module exports injects:
    module.exports.foo = foo;
    
    0 讨论(0)
  • 2020-11-22 05:14

    You can solve this easily: just export your data before you require anything else in modules where you use module.exports:

    classA.js

    class ClassA {
    
        constructor(){
            ClassB.someMethod();
            ClassB.anotherMethod();
        };
    
        static someMethod () {
            console.log( 'Class A Doing someMethod' );
        };
    
        static anotherMethod () {
            console.log( 'Class A Doing anotherMethod' );
        };
    
    };
    
    module.exports = ClassA;
    var ClassB = require( "./classB.js" );
    
    let classX = new ClassA();
    

    classB.js

    class ClassB {
    
        constructor(){
            ClassA.someMethod();
            ClassA.anotherMethod();
        };
    
        static someMethod () {
            console.log( 'Class B Doing someMethod' );
        };
    
        static anotherMethod () {
            console.log( 'Class A Doing anotherMethod' );
        };
    
    };
    
    module.exports = ClassB;
    var ClassA = require( "./classA.js" );
    
    let classX = new ClassB();
    
    0 讨论(0)
提交回复
热议问题