Javascript 嵌套猫鼬充满承诺

Javascript 嵌套猫鼬充满承诺,javascript,node.js,mongoose,Javascript,Node.js,Mongoose,我正在尝试填充我的模型,它看起来像: var Org = new mongoose.Schema({ _id: {type: String, unique:true}, //this will be the org code name: String, level: String, children: [{type: String, ref: 'Org'}] }); //Orgs have children orgs, w

我正在尝试填充我的模型,它看起来像:

var Org = new mongoose.Schema({
        _id: {type: String, unique:true}, //this will be the org code
        name: String,
        level: String,
        children: [{type: String, ref: 'Org'}]
    });

//Orgs have children orgs, which themselves can have children orgs at N levels
     req.Model.findOne({_id: id}).populate('children').exec(function(err, doc){
        if (err){
            return next(err);
        }
        req.Model.populate(doc, {path: 'children.children'}, function(err, doc){
            if(err){
                return next(err);
            }
            return res.json(doc);
        });
    });
{
   "status": "error",
   "serverTimestamp": "2014-07-24T18:23:02.974Z",
   "message": "\"function\" == \"undefined\""
}
给定一个组织,我想填充它的子组织,以及它的子组织等等。我可以在N=2个级别完成此操作:

var Org = new mongoose.Schema({
        _id: {type: String, unique:true}, //this will be the org code
        name: String,
        level: String,
        children: [{type: String, ref: 'Org'}]
    });

//Orgs have children orgs, which themselves can have children orgs at N levels
     req.Model.findOne({_id: id}).populate('children').exec(function(err, doc){
        if (err){
            return next(err);
        }
        req.Model.populate(doc, {path: 'children.children'}, function(err, doc){
            if(err){
                return next(err);
            }
            return res.json(doc);
        });
    });
{
   "status": "error",
   "serverTimestamp": "2014-07-24T18:23:02.974Z",
   "message": "\"function\" == \"undefined\""
}
几个小时以来,我一直试图通过承诺来实现上述目标,即使是在N=2的情况下。我认为对于N=*级别,使用mongoose内置实现的承诺会更干净

        req.Model.findOne({_id: id}).populate('children').exec()
        .then(function (doc){
            if(!treeView) {
                return doc;
            }
            return req.Model.populate(doc, {path: 'children.children'});
        })
        .then(function (doc){
            return res.json(doc);
        },function(err){
            return next(err);
        });

// treeView is a query string that lets me know that I need to populate the refs
我认为它应该按如下方式工作:

var Org = new mongoose.Schema({
        _id: {type: String, unique:true}, //this will be the org code
        name: String,
        level: String,
        children: [{type: String, ref: 'Org'}]
    });

//Orgs have children orgs, which themselves can have children orgs at N levels
     req.Model.findOne({_id: id}).populate('children').exec(function(err, doc){
        if (err){
            return next(err);
        }
        req.Model.populate(doc, {path: 'children.children'}, function(err, doc){
            if(err){
                return next(err);
            }
            return res.json(doc);
        });
    });
{
   "status": "error",
   "serverTimestamp": "2014-07-24T18:23:02.974Z",
   "message": "\"function\" == \"undefined\""
}
  • exec()返回一个承诺,我在第一次调用then()时开始处理该承诺
  • 如果treeView为false,则返回doc,它被视为原始承诺的解析,因此调用第二个then()处理程序。这确实发生了
  • 如果treeView为true,则对Model.populate的调用将返回另一个承诺,该承诺也将在对then()的第二次调用中得到处理
  • 我收到此错误:

    var Org = new mongoose.Schema({
            _id: {type: String, unique:true}, //this will be the org code
            name: String,
            level: String,
            children: [{type: String, ref: 'Org'}]
        });
    
    //Orgs have children orgs, which themselves can have children orgs at N levels
    
         req.Model.findOne({_id: id}).populate('children').exec(function(err, doc){
            if (err){
                return next(err);
            }
            req.Model.populate(doc, {path: 'children.children'}, function(err, doc){
                if(err){
                    return next(err);
                }
                return res.json(doc);
            });
        });
    
    {
       "status": "error",
       "serverTimestamp": "2014-07-24T18:23:02.974Z",
       "message": "\"function\" == \"undefined\""
    }
    
    我知道它会到达second then()的错误处理程序,因为我已经登出控制台进行验证,但我无法理解为什么会发生这种情况。一旦我能做到这一点,我将尝试让它在N=*级别上工作,我想这将涉及到递归地创建更多承诺。我在这里看到了许多相关的问题,但并不完全是我所需要的


    非常感谢您的帮助

    似乎是一个解决方案

    Q.ninvoke(doc, 'populate',{path: children.children})
    .then(function(doc){
        return res.json(doc);
    },function(err) {
        return next(err);
    });
    

    对我来说奇怪的是,我需要使用mongooses Document.populate而不是Model.populate(doc..),根据文档,它的行为应该非常相似,除了返回一个承诺。这是我不得不使用Q promise api的原因之一,因为Document.populate不会像Model.populate那样返回承诺。在没有常规节点样式回调的情况下,我无法使Model.populate正常工作,但此解决方案满足了我的需要。至于N=*层,我只需根据需要递归调用Q.ninvoke多次,扩展路径,就可以填充任意深度的层。

    我能够使用从Mongoose模型返回的Mongoose承诺在MongooseJS v4.1中使用嵌套子文档填充。无需使用其他promise库

    var fuelOrderId = req.params.fuelOrderId;
    fuelOrderModel.findById(fuelOrderId).populate('aircraftId')
    .then(function(order){
        return fuelOrderModel.populate(order,
             {path: 'aircraftId.aircraftContacts', 
              model: 'aircraftContactModel'});
    })
    .then(function(result){
        res.json({
            fuelOrder: result,
            status: 1
        });
    },function(err){
        console.error(err);
        res.json({err: err, status: 0});
    })
    

    <> > >编辑< /强>考虑使用<代码> .CcChh()/Cyto>而不是第二个错误函数。mpromise现在支持
    .catch()

    似乎这是唯一一种让文档填充到承诺链中的方法。非常感谢。