CommonJS / RequireJS - 循环模块依赖项

时间:2017-05-26 12:10:48

标签: requirejs circular-dependency commonjs

我想问一下commonjs / requirejs循环模块依赖恢复背后的机制是什么。

让我举个例子。让我们假设我们有以下模块结构

 modulea
     index.js
     submodulea_a.js
     submodulea_b.js

moduleb
     index.js
     submoduleb_a.js
     submoduleb_b.js

其中modulea / index.js和moduleb / index.js只是重新导出了子模块的有趣功能。即:

 var aa_class = require("./submodulea_a").aaclass;
 var ab_class = require("./submodulea_b").abclass;

 module.exports aa_class;
 module.exports ab_class;

另外,我们假设在子模块中我会做:

 var ba_class = require("moduleb").ba_class;

同样适用于B,但我们可以说在子模块b中我会这样做:

var aa_class = require("modulea").aa_class;

正如你所看到的,一个类在模块之间没有直接循环依赖,但是存在循环模块依赖,因为modulea需要moduleb而moduleb需要modulea(更好的说,从子模块重新导出某些东西)。 p>

如何通过节点commonjs或requirejs解决这个问题以避免堆栈溢出?是否有类似"后期绑定"管他呢?据我所知,我会说不,因为commonjs是同步的。

由于

修改

所以我对所描述的模块结构进行了一些研究,看起来它的工作方式类似于以下过程:

  1. 解析模块名称(package.json,node_modules,relative paths ...)
  2. 加载模块代码(.js文件)
  3. 标记正在初始化(已解决)的当前模块
  4. 准备"空" ({})为当前模块导出并发布它(其他模块将在require期间使用它进行导入,即使它是空的)
  5. 处理加载的模块(执行它),如果找到需要,请以与当前模块相同的方式解析模块
  6. 模块执行完成后,将其标记为初始化(已解决)
  7. 如果需要再次加载已初始化或初始化的模块,则使用其导出的缓存版本。

    无法解决的问题:

    当即将加载循环模块时,似乎无法解决:

    var aa_class = require("modulea").aa_class;
    
    模块A内部的模块A的aa_class在模块A的初始化时不可用,因为模块A的初始化在从模块A导出aa_class之前将执行交给模块B.所以只有一件事模块B可用的是来自模块A的空导出对象。我无法找到解决这个问题的方法,因为如果我想扩展bb_module中的aa_class,我就会丢失。

2 个答案:

答案 0 :(得分:0)

  

是否有类似“后期绑定”或其他什么?

有了RequireJS,有。你可以称之为“后期绑定”或“延迟加载”。

Circular Dependencies上的文档使用此示例。

background-size: contain;

答案 1 :(得分:0)

只要未在文件的顶层使用模块,就可以在导出当前模块后的 之后导入它们。

a.js:

class A {
  getB() { return new B() }
}

module.exports = A
const B = require('./b.js')

b.js:

class B {
  getA() { return new A() }
}

module.exports = B
const A = require('./a.js')