如何处理Node.js中的循环依赖关系

我最近一直在使用nodejs,并且仍然要处理模块系统,因此很抱歉这是一个明显的问题。我想要大致如下的代码:

a.js(主文件与节点一起运行)

var ClassB = require("./b");

var ClassA = function() {
    this.thing = new ClassB();
    this.property = 5;
}

var a = new ClassA();

module.exports = a;

b.js

var a = require("./a");

var ClassB = function() {
}

ClassB.prototype.doSomethingLater() {
    util.log(a.property);
}

module.exports = ClassB;

我的问题似乎是我无法从ClassB实例中访问ClassA实例。

有没有正确/更好的方法来构造模块来实现我想要的?是否有更好的方式在模块之间共享变量?

Mandy村村2020/03/24 18:01:59

其实我最终要求我依赖

 var a = null;
 process.nextTick(()=>a=require("./a")); //Circular reference!

不漂亮,但是可以。它比更改b.js(例如,仅增加modules.export)更容易理解和诚实,否则它就是完美的。

小小Davaid达蒙2020/03/24 18:01:59

与lanzz和setect的答案类似,我一直在使用以下模式:

module.exports = Object.assign(module.exports, {
    firstMember: ___,
    secondMember: ___,
});

Object.assign()成员复制到exports已提供给其他模块对象中。

=分配在逻辑上是多余的,因为它只是module.exports对其自身进行设置,但是我正在使用它,因为它可以帮助我的IDE(WebStorm)识别这firstMember是该模块的属性,因此“转到->声明”(Cmd-B)其他工具也可以在其他文件中使用。

这种模式不是很漂亮,因此我仅在需要解决循环依赖问题时才使用它。

Gil伽罗小宇宙2020/03/24 18:01:59

那么只有在需要时才需要懒惰吗?因此,您的b.js如下所示

var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
    var a = require("./a");    //a.js has finished by now
    util.log(a.property);
}
module.exports = ClassB;

当然,最好将所有require语句放在文件顶部。但是在某些情况下,我会原谅我从其他不相关的模块中挑选了一些东西。称其为hack,但有时这比引入进一步的依赖关系,添加额外的模块或添加新的结构(EventEmitter等)要好。

斯丁前端2020/03/24 18:01:59

有时引入第三类是真的是人为的(正如JohnnyHK所建议的那样),所以除了Ianzz:如果您确实想替换module.exports,例如,如果您正在创建一个类(例如,在b.js文件中)上面的示例),这也是可能的,只要确保在循环通告require的文件中,“ module.exports = ...”语句出现在require语句之前。

a.js(主文件与节点一起运行)

var ClassB = require("./b");

var ClassA = function() {
    this.thing = new ClassB();
    this.property = 5;
}

var a = new ClassA();

module.exports = a;

b.js

var ClassB = function() {
}

ClassB.prototype.doSomethingLater() {
    util.log(a.property);
}

module.exports = ClassB;

var a = require("./a"); // <------ this is the only necessary change
古一小哥2020/03/24 18:01:59

尽管node.js确实允许循环require依赖,但正如您所发现的那样,它可能很凌乱,您最好重组代码以使其不需要。也许创建一个使用其他两个类来完成您需要的第三类。

神奇老丝2020/03/24 18:01:59

尝试在上设置属性module.exports,而不是完全替换它。例如,module.exports.instance = new ClassA()在中a.jsmodule.exports.ClassB = ClassB在中b.js当建立循环模块依赖关系时,需求模块会module.exports从需求模块中获取不完整的引用,您可以在后面添加其他属性,但是当您设置了整个模块时module.exports,您实际上创建了一个新对象,该对象没有需求模块访问方式。