Leo*_*rdo 2 javascript module circular-dependency ecmascript-6 es6-modules
我在Babel环境中的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)
Run Code Online (Sandbox Code Playgroud)
我像这样导入它们:
// stores/index.js
import A from './A';
import B from './B';
import C from './C';
export {
A,
B,
C
}
Run Code Online (Sandbox Code Playgroud)
从我的应用程序入口点我做:
import * as stores from './stores';
Run Code Online (Sandbox Code Playgroud)
我希望(希望)预期执行顺序为A - > B - > C但实际上它是A-> C-> B.
这是由于模块B导入C,所以C模块在之前被评估B模块.这在C的设置中产生了问题,因为在那种情况下B将是未定义的.
我已经看到了类似的问题,但我不确定init函数是否是最好的解决方案,看起来有点hacky.
问:在ES6中解决这种可能适用于不同环境(Babel,Rollup)的循环依赖的最佳实践是什么?
ES6中循环依赖的最佳实践是什么?
完全避免它们.如果您不能(或者不想)完全避免它们,请将所涉及的模块限制为仅使用具有循环依赖关系的函数声明,而不是使用导入的值(包括extends引用)初始化顶级值(常量,变量,类) .
什么可能在不同的环境中工作(Babel,Rollup)?
模块解析和初始化的顺序在ES6规范中定义,因此在所有ES6环境中都应该相同 - 无论模块如何加载以及如何解析标识符.
如何解决这种循环依赖设置?
如果确实存在循环依赖关系X -> Y -> Z -> … -> X -> …,则需要建立起点.假设您希望X首先加载,尽管它依赖于此Y,因此您需要确保X从不使用任何导入的值,直到圆圈中的所有模块都完全初始化为止.所以,你打破的圆圈X和Y,你将需要在开始导入链Y-它会递归遍历的依赖,直到它停止在X,它具有尚未得到初始化没有进一步的依赖关系,所以这将是第一个模块被评估.
您必须遵循的规则是在导入圆圈中的任何其他模块之前始终导入.如果您甚至一次不使用这个常见的单一入口点到圆圈,您的纸牌将崩溃.Y
在您的特定示例中,这意味着index.js需要使用
import A from './A';
import C from './C'; // entry point to circular dependencies
import B from './B';
…
Run Code Online (Sandbox Code Playgroud)