Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 关于模型创建的Mongoose无限循环 背景_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

Javascript 关于模型创建的Mongoose无限循环 背景

Javascript 关于模型创建的Mongoose无限循环 背景,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我有关于调查的猫鼬模式,需要检查调查是否属于另一个集合中的一组国家 代码 为了检查这一点,我有一个surveySchema、一个countrySchema和一个创建模型并连接到DB的文件 为了检查调查是否属于有效的国家/地区,我在surveySchema中使用如下内容: surveySchema.js: "use strict"; const mongoose = require("mongoose"); const surveySchema = { subject: { type:

我有关于调查的猫鼬模式,需要检查调查是否属于另一个集合中的一组国家

代码 为了检查这一点,我有一个surveySchema、一个countrySchema和一个创建模型并连接到DB的文件

为了检查调查是否属于有效的国家/地区,我在surveySchema中使用如下内容:

surveySchema.js:

"use strict";

const mongoose = require("mongoose");

const surveySchema = {
    subject: { type: String, required: true },
    country: {
        type: String,
        validate: {
            validator: {
                isAsync: true,
                validator: async function(val, callback) {

                    const {
                        Country
                    } = require("./models.js").getModels();

                    const countriesNum = await Country.find({"isoCodes.alpha2": val}).count();
                    callback(countriesNum === 1);
                }
            },
            message: "The country {VALUE} is not available in the DB at the moment."
        }
    }
};


module.exports = new mongoose.Schema(surveySchema);
module.exports.surveySchema = surveySchema;
"use strict";

const mongoose = require("mongoose");

const countrySchema = {
    name: { type: String, required: true },
    isoCodes:{
        alpha2: { type: String, required: true }
        }
    }
};


module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;
"use strict";

const mongoose = require("mongoose");
const fs = require("fs");

const DB_CONFIG = "./config/dbConfig.json";

/**
 *  Module responsible for initializing the Models. Should be a Singleton.   
 */
module.exports = (function() {
    let models;

    const initialize = () => {

        //Connect to DB
        const {
            dbConnectionURL
        } = JSON.parse(fs.readFileSync(DB_CONFIG, "utf8"));

        mongoose.connect(dbConnectionURL);
        mongoose.Promise = global.Promise;

        //Build Models Object
        models = {
            Country: mongoose.model('Country', require("./countrySchema.js")),
            Survey: mongoose.model('Survey', require("./surveySchema.js"))
        };

    };

    const getModels = () => {
        if (models === undefined)
            initialize();

        return models;
    };

    return Object.freeze({
        getModels
    });
}());
countrySchema.js:

"use strict";

const mongoose = require("mongoose");

const surveySchema = {
    subject: { type: String, required: true },
    country: {
        type: String,
        validate: {
            validator: {
                isAsync: true,
                validator: async function(val, callback) {

                    const {
                        Country
                    } = require("./models.js").getModels();

                    const countriesNum = await Country.find({"isoCodes.alpha2": val}).count();
                    callback(countriesNum === 1);
                }
            },
            message: "The country {VALUE} is not available in the DB at the moment."
        }
    }
};


module.exports = new mongoose.Schema(surveySchema);
module.exports.surveySchema = surveySchema;
"use strict";

const mongoose = require("mongoose");

const countrySchema = {
    name: { type: String, required: true },
    isoCodes:{
        alpha2: { type: String, required: true }
        }
    }
};


module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;
"use strict";

const mongoose = require("mongoose");
const fs = require("fs");

const DB_CONFIG = "./config/dbConfig.json";

/**
 *  Module responsible for initializing the Models. Should be a Singleton.   
 */
module.exports = (function() {
    let models;

    const initialize = () => {

        //Connect to DB
        const {
            dbConnectionURL
        } = JSON.parse(fs.readFileSync(DB_CONFIG, "utf8"));

        mongoose.connect(dbConnectionURL);
        mongoose.Promise = global.Promise;

        //Build Models Object
        models = {
            Country: mongoose.model('Country', require("./countrySchema.js")),
            Survey: mongoose.model('Survey', require("./surveySchema.js"))
        };

    };

    const getModels = () => {
        if (models === undefined)
            initialize();

        return models;
    };

    return Object.freeze({
        getModels
    });
}());
models.js:

"use strict";

const mongoose = require("mongoose");

const surveySchema = {
    subject: { type: String, required: true },
    country: {
        type: String,
        validate: {
            validator: {
                isAsync: true,
                validator: async function(val, callback) {

                    const {
                        Country
                    } = require("./models.js").getModels();

                    const countriesNum = await Country.find({"isoCodes.alpha2": val}).count();
                    callback(countriesNum === 1);
                }
            },
            message: "The country {VALUE} is not available in the DB at the moment."
        }
    }
};


module.exports = new mongoose.Schema(surveySchema);
module.exports.surveySchema = surveySchema;
"use strict";

const mongoose = require("mongoose");

const countrySchema = {
    name: { type: String, required: true },
    isoCodes:{
        alpha2: { type: String, required: true }
        }
    }
};


module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;
"use strict";

const mongoose = require("mongoose");
const fs = require("fs");

const DB_CONFIG = "./config/dbConfig.json";

/**
 *  Module responsible for initializing the Models. Should be a Singleton.   
 */
module.exports = (function() {
    let models;

    const initialize = () => {

        //Connect to DB
        const {
            dbConnectionURL
        } = JSON.parse(fs.readFileSync(DB_CONFIG, "utf8"));

        mongoose.connect(dbConnectionURL);
        mongoose.Promise = global.Promise;

        //Build Models Object
        models = {
            Country: mongoose.model('Country', require("./countrySchema.js")),
            Survey: mongoose.model('Survey', require("./surveySchema.js"))
        };

    };

    const getModels = () => {
        if (models === undefined)
            initialize();

        return models;
    };

    return Object.freeze({
        getModels
    });
}());
这里的想法是,我在其他地方也使用了models.js文件。因为这个文件还负责连接到数据库,所以我决定将其设置为单例。这样,我应该只连接一次,所有进一步的请求将始终返回相同的模型,这将是理想的

问题 这里的问题是,我有一个循环依赖,导致:

RangeError: Maximum call stack size exceeded at exports.isMongooseObject (/home/ubuntu/workspace/server/node_modules/mongoose/lib/utils.js:537:12)

导致此错误的代码流是:

  • 代码运行getModels()`
  • getModels()
    检查
    models
    是否未定义并运行
    initialize()
  • initialize()
    尝试创建模型
  • 创建调查模型时,
    Survey:mongoose.model('Survey',require(“./surveySchema.js”)
    会运行到
    验证程序
    函数中,该函数再次需要
    models.js
  • 无限循环开始
  • 问题
  • 有没有其他方法可以在不进行异步验证的情况下检查调查的国家/地区是否是县集合的一部分
  • 如何构造/更改代码以避免这种情况发生

  • 正如评论中所说,我认为您对如何使用models.js模块感到有点困惑。我认为这就是正在发生的事情:

    您正在从models.js导出单个函数:

    models.js

    module.exports = function() { ... };
    
    const models = require("./models.js");
    
    module.exports = (function() {
        // codez here
        return Object.freeze({
            getModels
        });
    })();  // immediately invoke the function.
    
    因此,当您需要它时,您只需获得单一功能:

    surveySchema.js

    module.exports = function() { ... };
    
    const models = require("./models.js");
    
    module.exports = (function() {
        // codez here
        return Object.freeze({
            getModels
        });
    })();  // immediately invoke the function.
    
    型号
    现在是一项功能。这意味着每次调用它时,您都会运行models.js中的代码,并创建一个新变量
    let models,以及新函数
    initialize()
    getModels()

    您可以将
    let models
    从匿名函数移到全局范围内,这可能会修复它,但就我的钱而言,您只想在models.js中运行匿名函数一次,因此我会将模块的导出设置为其结果:

    models.js

    module.exports = function() { ... };
    
    const models = require("./models.js");
    
    module.exports = (function() {
        // codez here
        return Object.freeze({
            getModels
        });
    })();  // immediately invoke the function.
    
    使用它:

    // models is now the frozen object returned
    const { Survey } = models.getModels();
    
    至于验证选项,如果正常异步验证不能使用中所述的串行或并行机制为您添加自己的中间件验证代码,那么您没有理由不能添加自己的中间件验证代码

    评论后更新 您指出的第二个问题是,在第一次执行
    getModels()->initialize()
    期间,您调用
    require('./surveySchema.js')
    ,但这调用了
    getModels()
    ,它仍在被调用的过程中,尚未初始化
    模型,因此重新输入
    initialize()

    我认为您试图实现的是很好的(调查模式取决于客户模型),因为您仍然可以绘制没有任何循环依赖关系的对象图,而您实现它的方式就是这样的。我认为处理这个问题的最简单方法实际上是保留循环引用,但推迟调用
    surveySchema.js中的
    getModels()

    "use strict";
    
    const mongoose = require("mongoose");
    
    const models = require("./models.js");
    
    const surveySchema = {
        subject: { type: String, required: true },
        country: {
            type: String,
            validate: {
                validator: {
                    isAsync: true,
                    validator: async function(val, callback) {
                        // !! moved from the global scope to here, where we actually use it  
                        const {
                            Country
                        } = models.getModels();
    
                         const countries = await Country.find({"isoCodes.alpha2": val});
                         callback(countries.length === 1);
                    }
                },
                message: "The country {VALUE} is not available in the DB at the moment."
            }
        }
    };
    
    module.exports = new mongoose.Schema(surveySchema);
    module.exports.surveySchema = surveySchema;
    
    不过,一种更简洁且可能更具扩展性的方法可能是将连接代码与模型代码分开,因为这是一个完全不同的概念

    更多评论后更新#2 您看到的无限堆栈是因为您没有正确使用API。你有:

    const surveySchema = {
        country: {
            validate: {
                validator: {
                    isAsync: true,
                    validator: async function(val, callback) {...}
                },
            },
            ...
        }
    };
    
    你应该:

    const surveySchema = {
        country: {
            validate: {
                isAsync: true,
                validator: async function(val, callback) {...}
            },
            ...
        }
    };
    

    根据。

    为什么您认为异步验证不是一个好方法?而且您的单例不起作用,因为每次调用
    models()
    let models运行。所以它总是没有定义的。如果你选择
    让模型
    模块之外。exports
    可能会解决这个问题。我认为异步验证可能不是这里的答案,因为我需要包含来自另一个模式的模型。至于
    let models
    语句,将其置于函数之外也不能解决问题。也许我不够清楚。作为一个在这里寻求帮助的人,我自己完全理解并测试给我的每一个建议。当我说你的建议不起作用时,我的意思是我已经测试了它,它不起作用=(我已经更新了我的答案以反映你的建议,但正如我所说的,它仍然不起作用,因为变量
    models
    始终是
    未定义的
    。你确定代码到达
    models={…
    第一次调用models.js,第二次调用
    .getModels()
    之前,在models.js中的行?很好。因此,代码流运行
    models.js
    来创建模型。但是,在
    models.js
    中,我尝试创建调查模式,该模式调用
    const{Country}=models.getModels();
    ,它又尝试再次运行
    models.js
    文件。但是,该文件仍在尝试从第一次开始创建模型,因此在第二次运行中,变量
    models
    显然是
    未定义的
    。我在这里几乎陷入了一个循环。这是一个我没有解决的架构问题解决方案还没有…也许我应该更新我的问题?我不知道如何解决这个问题…好吧,如果我按照你的建议去做,我会得到一个
    超过最大调用堆栈大小的
    错误。甚至当我在验证器函数中定义
    const{Country}…
    时也会发生这种情况。这意味着我可能有一个无限递归b