Circular Dependencies in modules using requireJs

前端 未结 3 1043
执念已碎
执念已碎 2021-01-04 20:47

Reading the requireJs documentation,
in order to fix the Circular Dependencies, is suggested to use exports to create an empty object for the module that is

相关标签:
3条回答
  • 2021-01-04 21:19

    You should be able to use the synchronous version of require() in your B module to access the "A" module:

    // B module
    define([
        'a',
        'exports'
    ], function (a, exports) {
        console.log('A:', a); // A, undefined (as I was expecting)
        exports.A = function () {
            return require('a');
        }
        ...
    });
    
    0 讨论(0)
  • 2021-01-04 21:32

    One option would be not to return the module itself, but a function that instantiates the module (in this example it would a constructor as defined in typescript, at the bottom is the generated js code -note that interfaces do not generate .js code)

    • File IA.ts

      /// <reference path="IB.ts" />
      interface IA{
          funcA();
          _classB : IB;
      }
      
    • File IB.ts

      /// <reference path="IA.ts" />
      interface IB{
          funcB();
          _classA : IA;
      }
      
    • File ClassA.ts

      /// <reference path="IA.ts" />
      /// <reference path="IB.ts" />
      
      export class ClassA implements IA
      {
          _classB : IB = null;
      
          constructor(classB : IB)
          {
              this._classB = classB;
              if (classB){
                  this._classB._classA = this;
              }
              return this;
          }
      
          funcA(){
              console.log('I am ClassA');
          }
      }
      
    • File ClassB.ts

      /// <reference path="IA.ts" />
      /// <reference path="IB.ts" />
      export class ClassB implements IB
      {
          _classA : IA = null;
          constructor(classA : IA)
          {
              this._classA = classA;
              if (classA){
                  this._classA._classB = this;
              }
              return this;
          }
          funcB(){
              console.log('I am ClassB');
          }
      }
      
    • File MainTest.ts

      /// <reference path="../../def/require.d.ts" />
      /// <reference path="IA.ts" />
      /// <reference path="IB.ts" />
      define(['ClassA', 'ClassB'],
          function (classA, classB)
          {
              var aa : IA = new classA.ClassA();
              var bb : IB = new classB.ClassB(aa);
      
              bb.funcB();
              aa._classB.funcB();
              bb._classA.funcA();
              aa.funcA();
          });
      

    And the generated js code:

    • File ClassA.js

      define(["require", "exports"], function(require, exports) {
          var ClassA = (function () {
              function ClassA(classB) {
                  this._classB = null;
                  this._classB = classB;
                  if (classB) {
                      this._classB._classA = this;
                  }
                  return this;
              }
              ClassA.prototype.funcA = function () {
                  console.log('I am ClassA');
              };
              return ClassA;
          })();
          exports.ClassA = ClassA;
      });
      
    • File ClassB.js

      define(["require", "exports"], function(require, exports) {
          var ClassB = (function () {
              function ClassB(classA) {
                  this._classA = null;
                  this._classA = classA;
                  if (classA) {
                      this._classA._classB = this;
                  }
                  return this;
              }
              ClassB.prototype.funcB = function () {
                  console.log('I am ClassB');
              };
              return ClassB;
          })();
          exports.ClassB = ClassB;
      });
      
    • File MainTest.js

      define(['ClassA', 'ClassB'], function (classA, classB) {
      
          var aa = new classA.ClassA();
          var bb = new classB.ClassB(aa);
      
          bb.funcB();
          aa._classB.funcB();
          bb._classA.funcA();
          aa.funcA();
      
      });
      

    finally, the output will be:

    I am ClassB

    I am ClassB

    I am ClassA

    I am ClassA

    0 讨论(0)
  • 2021-01-04 21:36

    I often have circular issues using AMD modules to build an application core that both stands up many modules and contains config or other useful objects for those modules to use.

    I did some experimenting today and this seems to work pretty well.

    define(['exports', 'underscore', './config', './mediator'],
      function (exports, _, Backbone, config, Mediator){
    
        Core = /* ... */
    
        // Publicize a core 'singleton' so that it's dependencies can access it, and so can modules that define it as a dependency themselves.
        core = new Core()
        exports.core = core //publicize it in a way that supports circularity
        return core // And also publicize it normally
      }
    )
    

    The objects are both '===' equal to each other, so this seems very promising.

    EDIT:

    The above method doesn't work when optimized. Here's another method that may (untested): https://github.com/requirejs/example-multipage/blob/master/www/js/app/main1.js#L2

    define(function (require) {
      var $ = require('jquery'),
          lib = require('./lib'),
          Core;
    
       Core = /* ... */
    
       return new Core()
    });
    
    0 讨论(0)
提交回复
热议问题