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

我了解正在发生的事情以及原因,但是我找不到解决方法。我尝试了堆栈提供的答案,并浏览了Google的许多文章,但都没有走运。
我尝试将exports移到require之前,将结构声明为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一个.validate()方法,然后从您所需要的属性验证器中调用它即可确实在Class_A文件中定义。


  我尝试将exports移到require之前,将我的结构声明为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,
};


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

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

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:如何解决循环依赖关系?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54205763/

10-15 23:56