如何处理循环依赖?

时间:2014-11-07 19:49:50

标签: requirejs circular-dependency

假设:

  • StringPreconditions扩展ObjectPreconditions
  • ObjectPreconditions取决于StringPreconditions(其中一个方法返回子类)
  • PreconditionsObjectPreconditionsStringPreconditions的守门人(确保在返回实例之前加载它们)
  • User取决于Preconditions

我有这段代码:

define(["ObjectPreconditions"], function(ObjectPreconditions)
{
  console.log("Inside StringPreconditions");

  function StringPreconditions() {}
  StringPreconditions.prototype = Object.create(ObjectPreconditions.prototype);
  StringPreconditions.prototype.constructor = ObjectPreconditions;
  return StringPreconditions;
});

define(["require"], function(require)
{
  console.log("Inside ObjectPreconditions");

  // Resolve circular dependencies
  var StringPreconditions;
  require(["StringPreconditions"], function(theStringPreconditions)
  {
    StringPreconditions = theStringPreconditions;
    console.log("ObjectPreconditions finished loading StringPreconditions");
  });

  function ObjectPreconditions() {}
  ObjectPreconditions.prototype.isInstanceOf(type)
  {
    console.log("ObjectPreconditions.isInstanceOf() invoked");
    if (type === String)
      return new StringPreconditions();
  }
});

define(["ObjectPreconditions", "StringPreconditions"], function(ObjectPreconditions, StringPreconditions)
{
  console.log("Inside Preconditions");
  var Preconditions = {};

  Preconditions.requireThat(parameter) = function()
  {
    return new ObjectPreconditions(parameter);
  };
  return Preconditions;
});

define(["Preconditions"], function(Preconditions)
{
  console.log("Inside User");
  function User() {}
  User.prototype.doSomething = function()
  {
    var StringPrecondition = Preconditions.requireThat("test").isInstanceOf(String);
  }
});

问题在于我有10%的时间收到此加载顺序:

  • 内部用户
  • 内部先决条件
  • Inside ObjectPreconditions
  • Inside StringPreconditions
  • ObjectPreconditions.isInstanceOf()( CRASH ,因为StringPreconditions未定义)
  • ObjectPreconditions已完成加载StringPreconditions

我已经阅读了http://requirejs.org/docs/api.html#circular,但我相信他们正在做同样的事情。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

更新:https://stackoverflow.com/a/42264822/14731包含ES6模块的更新答案。


我明白了:我们需要创建一个"看门人"将定义依赖于循环依赖的函数的文件。

  1. ObjectPreconditions.js重命名为AbstractObjectPreconditions.js
  2. 创建一个新的ObjectPreconditions.js文件(我们的新网守)。
  3. AbstractObjectPreconditions.js中的任何循环依赖项移至ObjectPreconditions.js
  4. 用户代码应为require(ObjectPreconditions)。循环依赖中涉及的代码(例如子类)应require(AbstractObjectPreconditions)
  5. 以下是生成的代码:

    define(["AbstractObjectPreconditions"], function(ObjectPreconditions)
    {
      console.log("Inside StringPreconditions");
    
      function StringPreconditions() {}
      StringPreconditions.prototype = Object.create(ObjectPreconditions.prototype);
      StringPreconditions.prototype.constructor = ObjectPreconditions;
      return StringPreconditions;
    });
    
    define(["require"], function(require)
    {
      console.log("Inside AbstractObjectPreconditions");
    
      function ObjectPreconditions() {}
      return ObjectPreconditions;
    });
    
    define(["AbstractObjectPreconditions"], function(ObjectPreconditions)
    {
      // Gatekeeper for circular dependencies
      ObjectPreconditions.prototype.isInstanceOf(type)
      {
        console.log("ObjectPreconditions.isInstanceOf() invoked");
        if (type === String)
          return new StringPreconditions();
      }
    
      return ObjectPreconditions;
    });
    
    
    define(["ObjectPreconditions", "StringPreconditions"], function(ObjectPreconditions, StringPreconditions)
    {
      console.log("Inside Preconditions");
      var Preconditions = {};
    
      Preconditions.requireThat(parameter) = function()
      {
        return new ObjectPreconditions(parameter);
      };
      return Preconditions;
    });
    
    define(["Preconditions"], function(Preconditions)
    {
      console.log("Inside User code");
      function User() {}
      User.prototype.doSomething = function()
      {
        var StringPrecondition = Preconditions.requireThat("test").isInstanceOf(String);
      }
    });