【问题标题】:Creating Mongoose organization/class structure?创建 Mongoose 组织/类结构?
【发布时间】:2017-12-11 05:38:50
【问题描述】:

我正在使用 Node.js、Express 和 Mongoose/MongoDB 构建一个 Web 应用程序。

我遇到的一个问题是如何正确组织和构建与 Mongoose 相关的方法。我需要在我的路由中调用 Mongoose 功能,但所有示例都显示使用 Mongoose 调用,而无需使用原型构建单独的文件或类。

IE。设置架构并在路由中调用 mongoose

SiteModel.find({}, function(err, docs) {
if (!err){ 
    console.log(docs);
    process.exit();
} else {throw err;}
});

我想将 mongoose CRUD 函数放在与逻辑和功能相关的帮助文件中,并在我的路由中调用它们。当我对 mongoose 使用单独的类方法时,没有返回值(或者由于异步性质我无法使用结果)

//Router file
var myService =  require('../helpers/ServiceStatus');

router.get('/', authService.isLoggedIn, function(req,res){

   var serviceObject = new myService(); //Initialize class with Mongoose functions

   async.parallel({
       modelAFind: function(cb){
           //Mongoose class method is called
           var response= serviceObject.getAllServiceDetails(); 
           cb(null, response);
       },
       modelBFind: function(cb){
           cb(null, 2); //filler
       }
   }, function(results){
       console.log("Results of query: " + results);
   });

来自我创建服务对象的 Mongoose 类的片段:

//ServiceStatus.js
//Constructor
function ServiceStatus() {

}

ServiceStatus.prototype.getAllServiceDetails = function(){

    var query = SiteModel.find({});
    var promise = query.exec();

    promise.then(function (doc) {
        return doc;
    });
};

处理异步的最佳方法是什么,使用 Mongoose 逻辑构建单独的帮助文件并在路由中调用它们:promise、带有回调的函数等?谢谢。

*编辑 - 添加架构文件

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// set up a mongoose model
module.exports = mongoose.model('SiteModel', new Schema({

    id: String,
    service: {type: String, unique: true, required: true},
    status: String,
    settings: Object,
    lastCheck: String

}

,{
    timestamps: true
}));

【问题讨论】:

    标签: javascript node.js express mongoose


    【解决方案1】:

    因此,在我们进入组织代码的“最佳”方式之前,您缺少几个关键的经验法则。

    1. 当您处理异步方法时,您必须始终处理 它们(及其调用代码)是异步的。在您的示例中,您的 getAllServiceDetails() 函数既不返回承诺也不返回 执行回调,因此您会丢失该上下文。
    2. 在同一个逻辑堆栈中同时使用 Promises 和 Callbacks 会增加 大脑的认知负荷;尝试坚持一种风格或 尽最大可能。

    至于最好的组织方式,我强烈在这种情况下抽出整个服务类,而是着眼于编写一个猫鼬插件,或者只是扩展猫鼬模式本身。如果您要为多个模型编写相同的代码,插件会更有用,所以我假设您不在这种情况下并继续仅针对 SiteSchema 的示例。你没有在这里显示你的架构代码,所以我不确定你真正节省了什么,不仅仅是在你的路由代码中调用SiteModel.find(...),而是为了争论,你可以这样做:

    SiteSchema.statics.list = function(cb) {
      SiteSchema.find({}, cb);
    }
    

    这使您不必在调用代码中传递空对象,但调用代码仍必须如下所示:

    /** snip **/
    modelAFind: function(cb){
           //Mongoose class method is called
           var response= serviceObject.list(cb); 
       },
    

    如果您使用的是最新版本的节点之一,您还可以访问 async/await 语法,这可能更符合您的喜好。请注意,我的示例未经过测试,但应该如下所示:

    SiteSchema.statics.list = async function() { // note the 'async' keyword 
      // latest versions of Mongoose, this returns a Promoise
      return SiteSchema.find({});
    }
    

    那么你的消费代码可以是

    /** snip **/
    modelAFind: function(cb){
           //Mongoose class method is called
           var response= await serviceObject.list(); // note 'await' keyword
           cb(null, response);
       },
    

    还要注意我没有添加错误处理;使用 async/await,您只需使用 try...catch。

    【讨论】:

    • 嗨,保罗,这是很好的信息。我已经为我的模型附加了架构文件。对于特定的“getter”和“setter”查询,您会在 Mongoose 模式中编写所有函数而不是单独的文件吗?
    • 是的,肯定会这样做。我只为跨越多个模型的逻辑创建服务类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多