Javascript ES6循环依赖。实现依赖中心

Javascript ES6循环依赖。实现依赖中心,javascript,ecmascript-6,getter,circular-dependency,Javascript,Ecmascript 6,Getter,Circular Dependency,我发现了很多关于循环依赖性的文章,指出了项目中的设计/架构缺陷。在大多数情况下,通过稍微重构类就可以很容易地解决这个问题 在这个例子中,我试图为依赖项创建一个中心。这是一个类库,可以由不同的项目导入。目标是在将返回依赖项实例的主类中包含getter。这个实例必须是一个单例,它存储在主类的依赖项中,下次如果有人调用getter,它将返回该类的同一个实例 下面是代码的外观: // deps import { DepA } from './dep-a'; import { DepB } from '

我发现了很多关于循环依赖性的文章,指出了项目中的设计/架构缺陷。在大多数情况下,通过稍微重构类就可以很容易地解决这个问题

在这个例子中,我试图为依赖项创建一个中心。这是一个类库,可以由不同的项目导入。目标是在将返回依赖项实例的主类中包含getter。这个实例必须是一个单例,它存储在主类的依赖项中,下次如果有人调用getter,它将返回该类的同一个实例

下面是代码的外观:

// deps

import { DepA } from './dep-a';
import { DepB } from './dep-b';

const depsKey = '__MY_DEPS__';

class Deps {
  dependencies = {};

  get depA() {
    return this.getDependency('depA', DepA);
  }  
  
  get depB() {
    return this.getDependency('depB', DepB);
  }  

  bind(key, value) {
    this.dependencies[key] = value;
  }

  getDependency(key, serviceClass) {
    let service = this.dependencies[key];

    if (!service && !!serviceClass) {
      // if instance is not created yet, we instantiate the class and put instance in the dependencies
      service = new serviceClass();
      this.bind(key, service);
    }

    return service;
  }
}

export const deps = (() => {
  window[depsKey] = window[depsKey] || new Deps();

  return window[depsKey];
})();

// dep-a

import { deps } from './deps';

export class DepA {
  methodA() {
    console.log(deps.depB);
  }
}

// dep-b

import { deps } from './deps';

export class DepB {
  methodB() {
    console.log(deps.depA);
  }
}
如您所见,这会产生一个循环依赖性问题,因为类Deps在其getter中使用类DepA和DepB来创建这些类的实例(如果它们不存在的话)。类DepA和DepB使用Deps的实例通过其getter相互检索

我希望这个解释不是很繁琐


有人能建议我需要做哪些更改来摆脱这里的循环依赖关系,但要想保持通过Deps类(Deps实例)访问单例的想法吗?

我的建议如下:

a-singleton.js b-singleton.js 然后,无论您在哪里需要这些单例,都可以导入文件并调用函数来获取单例


根据这些类的作用以及它们相互引用的方式/时间,您也可以直接导出默认的新DepA(),但这取决于它们相互引用的方式以及它们在实例化时需要执行的操作,我在这里展示的惰性方法可能更好,也可能是必要的。

如果
Deps
是单例,那么
DepA
不能导入
Deps
并注册自身吗?这就是我的方法。谢谢你的建议@loganfsmyth。您将如何从外部访问DepA,或者谁将触发DepA的实例化?您确定需要单例实例吗?很多时候,您可以获得相同的效果,但更理想的情况是,只使用模块和模块级常量来保存您需要的任何私有状态。您能澄清一下每个文件的实例是什么意思吗?我同意像这样的单例是非常罕见的,或者如果我有它们,我会实例化它们,然后从一个中心模块导出它们。循环依赖的问题是,你试图将单例的逻辑放在同一个地方,你不需要这样做,并引入循环。不要将DepA和DepB都导入一个负责实例化它们的文件中,而是将它们放在单独的文件中,让a-creation和b-creation逻辑管理它们自己的单例。当一个JS模块已经是一个单体时,根本没有理由存在一个
Deps
类。好的,谢谢@loganfsmyth。我明白了。我们将努力实施它。
import { DepA } from './dep-a'; 

let singleton;
export function getA() {
  if (!singleton) {
    singleton = new DepA();
  }
  return singleton;
}
import { DepB } from './dep-b'; 

let singleton;
export function getB() {
  if (!singleton) {
    singleton = new DepB();
  }
  return singleton;
}