0

我正在使用 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和其他模块可以使用是一个好主意。moduleBValidatemoduleASchemamoduleBSchema

问题是它会产生循环依赖问题,因为在上述情况下,我会:

//moduleAValidate.js
var moduleBSchema = require('../moduleBValidate').moduleBschema;

//moduleBValidate.js
var moduleASchema = require('../moduleAValidate').moduleAschema;

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

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

4

2 回答 2

0

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

于 2015-11-09T21:40:13.517 回答
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;
于 2015-11-16T15:38:45.020 回答