解决js循环依赖

问题

js 循环依赖,比如模块A和模块B都继承自基类模块C,但是C中的某些方法会引用到A或者B,这时候ACBC就是相互依赖的关系。在 ts 中经常会导入模块取类型,相互引用就很常见。

以下代码展示了这种循环依赖关系。

// --- 入口文件 index.js ---
import { C } from "./C";

new C();

// --- 基类模块 C.js ---
import { A } from "./A";
import { B } from "./B";

export class C {}

// --- 子模块 A.js ---
// 这里的import 会报错 Super expression must either be null or a function
import { C } from "./C";
export class A extends C {
  constructor() {
    super("");
  }
}

// --- 子模块 B.js ---
import { C } from "./C";
export class B extends C {
  constructor() {
    super("");
  }
}

这里有一个简单的示例,演示循环引用后报错无法执行

解决方案

建一个额外的公共模块,用来将所有的模块导入进来,再到导出去。如果一个模块要用其他模块的时候,就从这个公共模块中导入进来使用,相当于做一个中转站。

// --- 入口文件 index.js ---
import { C } from "./common";

new C();

// --- 公共模块导出文件 common.js ---
// 注意这里export * from "./C";一定要写在顶部,因为C模块是被A和C依赖的模块,需要优先缓存
export * from "./C";
export * from "./A";
export * from "./B";

// --- 基类模块 C.js ---
import { A } from "./common";
import { B } from "./common";

export class C {}

// --- 子模块 A.js ---
// 这里的import 会报错 Super expression must either be null or a function
import { C } from "./common";
export class A extends C {
  constructor() {
    super("");
  }
}

// --- 子模块 B.js ---
import { C } from "./common";
export class B extends C {
  constructor() {
    super("");
  }
}

这里有一个简单的示例,演示使用公共模块导出后解决循环引用问题

参考

评论