javascript - Node.js v.11.6.0 : How to resolve circular dependency?

标签 javascript node.js class circular-dependency

在我的应用程序中,我创建了许多 ES6“类”,每个类都与自定义 setter 一起定义其属性,其中在分配属性之前,它运行一个特定于字段的验证器。 现在,由于模型可能具有相同的可用字段,并且我不想重复验证器的代码,因此我计划根据需要导入模型,并在通过类的静态属性公开它们时重用验证器(检查代码更好地理解)。 不幸的是,这会导致循环依赖,并因此破坏整个事情。

我明白发生了什么以及为什么,但我找不到解决方法。我尝试了堆栈上提供的答案,并浏览了谷歌的许多文章,但没有运气。 我尝试在 require 之前移动 exports,将我的结构声明为 var 以使用提升,在 exports 之前声明空结构,然后之后再定义它们,还有很多很多。 我知道我可以通过将通用验证器移动到单独的文件并将其导入两个模块中来解决这种情况,但这不是我想要的,因为这并不能完全解决 future 的问题,因为我可能需要其他属性/方法被暴露。 另外 - 这似乎不太正确:ClassA 属性的验证器应该坚持使用 ClassA“域”,反之亦然。

现在是代码。这是我正在使用的简化但有效的版本:

// ClassA.js:
const { ClassB } = require('./ClassB');

// This prints: ClassA inside ClassB: undefined
console.log('ClassB inside ClassA:', ClassB);

const _validators = {
    // This is validator defined in ClassA...
    property_a: (value) => true,

    // ...And this one is reusing a validator from ClassB
    // I'm getting: TypeError: Cannot read property 'VALIDATORS' of undefined
    property_b: ClassB.VALIDATORS.property_b,
};

exports.ClassA = class ClassA {
    constructor() {
        // Here comes the code defining descriptors for each property 
        // and running the property-specific validator inside 
        // a field setter
    }

    // Expose class-specific validators as class property
    static get VALIDATORS () {
        return _validators;
    }
};
// ClassB.js:
const { ClassA } = require('./ClassA');

console.log('ClassA inside ClassB:', ClassA);

const _validators = {
    // This is validator defined in ClassA...
    property_a: ClassA.VALIDATORS.property_a,

    // ...And this one is reusing a validator from ClassB
    property_b: (value) => true,
};

exports.ClassB = class ClassB {
    constructor() {
        // Here comes the code defining descriptors for each property 
        // and running the property-specific validator inside 
        // a field setter
    }

    // Expose class-specific validators as class property
    static get VALIDATORS () {
        return _validators;
    }
};
// app.js
const { ClassA } = require('./ClassA');
const { ClassB } = require('./ClassB');

console.log(ClassA, ClassB);

由于循环导入 ClassB 中的 ClassA 是 未定义(尽管根据我读过的文章,它应该是 {}),在 控制台上可见。 log 并导致我收到错误:

TypeError: Cannot read property 'VALIDATORS' of undefined
    at Object.<anonymous> (/repository/ClassB.js:6:24)

如何在不创建另一个通用文件的情况下重新定义/重新排列代码以使其正常工作?

如有任何帮助,我们将不胜感激。

我正在使用:Node.js v.11.6.0

最佳答案

I know I can solve this case by moving common validators to a separate file and import it in both modules but that's not what I'm looking for.

正是您所需要的。做吧。没有什么问题。在您当前的演示代码中,两个 _validators 对象甚至看起来相同,它们的所有属性都是相同的 - 您甚至不需要创建两个不同的自定义对象,除了共享对象之外还具有特定属性。

Plus - it just doesn't seem right: ClassA properties' validators should stick with ClassA "domain" and vice versa.

似乎不正确的是,ClassA 公开了 ClassB.VALIDATORS.property_b,反之亦然。你为什么做这个?这两个类的耦合是否比应有的更紧密?看起来它们都有完全相同的属性名称。

此外,如果 property_b 将包含应验证的 Class_B 实例,并且您希望使用 Class_B 声明验证代码,则只需为 Class_B 提供 .validate() 方法,并从您在 Class_A 文件中定义的属性验证器调用它即可。

I tried moving exports before require, declaring my structures as var to use hoisting, and many, many more.

好吧,如果你看看这两个对象文字

const a_validators = {
    property_a: (value) => true,
    property_b: b_validators.property_b,
};
const b_validators = {
    property_b: (value) => true,
    property_a: a_validators.property_a,
};

绝对没有办法安排他们的评估顺序,以便两者都能得到想要的结果。你必须把它们分开。

另一个解决方案是将它们声明为半空,并在加载两个模块后延迟初始化其余部分。您可以使用 getter 来完成此操作 - 当覆盖 module.exports 而不是在其上创建属性时,您还需要将 require() 调用放在 getter 内。

const _validators = {
    property_a: (value) => true,

    get property_b() {
        const { ClassB } = require('./ClassB');
        return ClassB.VALIDATORS.property_b;
    }
};
// and vice versa

关于javascript - Node.js v.11.6.0 : How to resolve circular dependency?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54205763/

相关文章:

ruby - 判断祖先是Ruby中的类还是模块的方法?

c++ - 类转储创建的奇怪 CDStructures.h

javascript - 单击事件后如何触发函数 useEffect?

javascript - Firefox AddEventListener 问题

html - 如何在加载时预先选择单选按钮(Express/NodeJS/EJS)?

java - 在数组的另一个类中调用 getAverage 方法

javascript - 当没有其他可能性时,使用 "else if"代替 "else"

javascript - 向数据表添加按钮 - Jquery

javascript - 使用javascript在日常聊天中的字符串逻辑

javascript - 解析 VB 代码以获取注释