繁体   English   中英

Node.js v.11.6.0:如何解决循环依赖性?

[英]Node.js v.11.6.0: How to resolve circular dependency?

在我的应用程序内部,我创建了许多ES6“类”,每个类都定义了它的属性以及自定义设置器,在它们内部(分配属性之前),它正在运行特定于字段的验证器。 现在,由于模型可能具有相同的可用字段,并且我不想复制验证器的代码,因此我计划根据需要导入模型,并在通过类的静态属性公开验证器时重新使用验证器(请检查代码是否符合更好地了解)。 不幸的是,这导致了循环依赖,结果-破坏了整个事情。

我了解正在发生的事情以及原因,但是我找不到解决方法。 我尝试了堆栈提供的答案,并浏览了Google的许多文章,但都没有走运。 我试过在require之前移动exports ,将我的结构声明为var以使用提升,在exports之前声明空结构,然后在之后定义它们,等等。 我知道我可以通过将公共验证器移动到单独的文件并将其导入两个模块来解决这种情况,但这不是我想要的,因为这并不能完全解决将来的问题,因为我可能需要其他属性/方法被暴露。 另外-看起来似乎并不正确: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是undefined (尽管根据我读过的文章,它应该是{} )在console.log上可见,并导致我得到以下错误:

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

如何重新定义/重新排列代码以使其正常工作,而又不创建另一个公共文件?

任何帮助,将不胜感激。

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

我知道我可以通过将公共验证器移动到一个单独的文件并将其导入两个模块中来解决这种情况,但这不是我想要的。

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

另外-看起来似乎并不正确:ClassA属性的验证器应坚持使用ClassA“域”,反之亦然。

看起来不对的是, ClassA公开了ClassB.VALIDATORS.property_b ,反之亦然。 你为什么做这个? 这两类人之间的联系是否比应有的紧密? 看起来它们都具有完全相同的属性名称。

另外,如果property_b将包含应该验证的Class_B实例,并且您想使用Class_B声明验证代码,则只需给Class_B一个Class_B .validate()方法,然后从您在Class_A文件中定义的属性验证器中调用它Class_A

我试过在require之前移动exports ,将我的结构声明为var以使用提升,还有很多很多。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM