首页 > 解决方案 > ES6 循环依赖。实现依赖中心

问题描述

我发现了很多关于循环依赖的文章,它表明了项目中的设计/架构缺陷。在大多数情况下,可以通过稍微重构类来轻松修复它。

在此示例中,我尝试为依赖项创建一个集线器。这是一个可以被不同项目导入的类库。目标是在主类中拥有将返回依赖项实例的 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 实例)访问单例的想法?

标签: javascriptecmascript-6gettercircular-dependency

解决方案


我的建议是这样的:

a-singleton.js

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

let singleton;
export function getA() {
  if (!singleton) {
    singleton = new DepA();
  }
  return singleton;
}

b-singleton.js

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

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

然后无论你需要这些单例,你都可以导入文件并调用函数来获取单例。

根据这些类的作用以及它们相互引用的方式/时间,您也可以直接export default new DepA()做可以更好或必要。


推荐阅读