ES6模块和循环依赖

问题描述:

我有在ES6这个问题在通天环境

ES6模块和循环依赖

// A.js 
class A { 
} 
export default new A(); 

// B.js 
import C from './C'; 
class B { 
} 
export default new B(); 

// C.js 
import A from './A'; 
import B from './B'; 
class C { 
    constructor(A, B){ 
     this.A = A; 
     this.B = B; // undefined 
    } 
} 
export default new C(A, B) 

我导入它们是这样的:

// stores/index.js 
import A from './A'; 
import B from './B'; 
import C from './C'; 

export { 
    A, 
    B, 
    C 
} 

而且从我的应用程序入口点我做的:

import * as stores from './stores'; 

我(希望)预期执行顺序是A - >乙 - > C,但实际上它是A-> C-> B.
这是由于模块B导入了C,所以C模块在B模块之前被评估。这在C的设置中产生问题,因为在那种情况下,B将是undefined

我见过类似的question,但我不确定init函数是否是这里最好的解决方案,这似乎有点不合理。

问题:在ES6中解决这种循环依赖关系的最佳做法是什么?它可能适用于不同的环境(Babel,Rollup)?

+0

*预期执行的顺序是A - >乙 - > C * - 为其切入点?如果甚至没有使用C,为什么C在B中导入? – estus

+0

它被使用,这是一个缺少实现细节的例子。我已经更新了添加入口点的问题 – Leonardo

+0

省略的细节在这里改变了一切。不会有循环依赖,因为未使用的导入被跳过。考虑提供http://stackoverflow.com/help/mcve。同样仅仅为单例使用类是反模式。 – estus

有关ES6中循环依赖关系的最佳实践是什么?

完全避免它们。如果您不能(或不想)完全避免它们,请将涉及的模块仅限于使用具有循环依赖性的函数声明,从不使用导入的值初始化顶级值(常量,变量,类) extends参考)。

什么可能适用于不同的环境(Babel,Rollup)?

模块解析和初始化的顺序在ES6规范中定义,所以在所有ES6环境中都应该是相同的 - 不管模块如何加载以及如何解析其标识符。

如何解决这种循环依赖设置?

如果你确实有循环依赖X -> Y -> Z -> … -> X -> …,你需要建立一个起点。假设你想先加载X,虽然它取决于Y,所以你需要确保X从不使用任何导入的值,直到圆圈中的所有模块都完全初始化。所以你打破了XY之间的圆圈,你需要在Y处启动导入链 - 它将递归遍历依赖关系,直到它停在X之间,因为它没有进一步的依赖关系,所以没有被初始化,所以它会是第一个要评估的模块。

,你必须遵循那么规则是总是进口Y进口其他模块中的任何在圈内之前。如果你甚至有一次不使用这个通用的单一入口点,你的房子会崩溃。

在你的具体的例子,这意味着index.js将需要使用

import A from './A'; 
import C from './C'; // entry point to circular dependencies 
import B from './B'; 
…