如何在没有循环依赖的模型之间正确共享Hapi Joi验证模式

时间:2015-11-09 14:05:26

标签: javascript architecture hapijs joi

我正在使用HAPI和Joi创建API来验证输入,我在不同模块之间共享验证模式时遇到了麻烦。 我正在使用面向组件的架构,看起来像那样

components
|_ moduleA
   |_ moduleAController
   |_ moduleAModel
   |_ moduleARoute
   |_ moduleAValidate
|_ moduleB
   |_ moduleBController
   |_ moduleBModel
   |_ moduleBRoute
   |_ moduleBValidate
|_ moduleC
...

在每个模块中,moduleXRoute创建一个路由,该路由将moduleXController的处理程序与moduleXValidate的验证程序相关联。

当我使用Joi时,我正在对输入数据执行一些测试,问题出在哪里,我的moduleA保留了moduleB的列表,而moduleB保留了对moduleA的引用var moduleASchema = { _id: Joi.objectId(), name: Joi.string().required(), moduleB: Joi.array().items(Joi.alternatives().try(Joi.objectId(), moduleBSchema)), }; var moduleBSchema = { _id: Joi.objectId(), name: Joi.string().required(), moduleA: Joi.alternatives().try(Joi.objectId(), moduleASchema), }; ,因此在验证器中暗示:

moduleAValidate

这就是为什么,我认为moduleBValidatemoduleASchema公开其他模块可以使用的moduleBSchema//moduleAValidate.js var moduleBSchema = require('../moduleBValidate').moduleBschema; //moduleBValidate.js var moduleASchema = require('../moduleAValidate').moduleAschema; 是个好主意。

问题在于它产生循环依赖问题,因为在上面的例子中,我会:

<form name="ImportBulkAttendance" target="uploadFileJava" type="upload" default-map-name="content" focus-field-name="contentTypeId" header-row-style="header-row" default-table-style="basic-table">

    <field name="filename" title="filename">
        <file name="filename"/>
    </field>
    <field name="createButton">
        <submit button-type="button" />
    </field>
</form>

因此,处理问题的好方法是什么?

我发现简单的方法是将所有模式集中在一个文件中,这可能是所有验证器中都需要的,但我觉得它只是与组件体系结构相矛盾。

2 个答案:

答案 0 :(得分:0)

最好的方法是建立一个中心点,将模式的公共部分保存在中心位置,并在需要时加载到所需的模式中。

答案 1 :(得分:0)

我终于决定通过使用依赖注入解决鸡和蛋的问题。 在上面的例子中,我会做类似

的事情
//moduleBValidate.js
var moduleBSchema = new (require('moduleBSchema.js'))();
var moduleASchema = new (require('moduleASchema.js'))(moduleBSchema); // Here I use dependency injection for injecting moduleBSchema in moduleASchema

//moduleAValidate.js
var moduleASchema = new (require('moduleASchema.js'))();
var moduleBSchema = new (require('moduleBSchema.js'))(moduleASchema);

我用这种方式构建了joi架构:

function moduleASchema(moduleBSchema, moduleCSchema...) { // Here we put all dependencies of moduleASChema
    moduleBSchema = moduleBSchema || Joi.object();
    moduleCSchema = moduleCSchema || Joi.object();
    ...

    this.schema = {
        name: Joi.string().required(),
        moduleBRef: Joi.alternatives().try(Joi.objectId(), moduleBSchema),
        moduleCRef: Joi.alternatives().try(Joi.objectId(), moduleCSchema)
    };
    return this.schema;
}

module.exports = SiteSchema;