嵌套的猫鼬充满了承诺

时间:2014-07-24 19:41:50

标签: 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, which themselves can have children orgs at N levels

鉴于一个组织,我想填充其子女及其子女等。我可以为N = 2级别完成此任务:

     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);
        });
    });

现在几个小时我一直试图用承诺完成上述工作,即使在N = 2时也是如此。我认为对于N = *级别,使用mongoose具有内置实现的promise这样做会更干净。

        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

我认为它的工作原理如下:

  1. exec()返回一个promise,我在第一次调用then()
  2. 时开始处理
  3. 如果treeView为false,我返回doc,它被视为原始promise的解析,因此第二个then()处理程序被调用。这确实发生了。
  4. 如果treeView为true,则对Model.populate的调用将返回另一个promise,该promise也将在then()的第二次调用中得到处理。
  5. 我收到此错误:

    {
       "status": "error",
       "serverTimestamp": "2014-07-24T18:23:02.974Z",
       "message": "\"function\" == \"undefined\""
    }
    

    我知道它会到达第二个then()的错误处理程序,因为我已经注销到控制台进行验证,但我无法弄清楚为什么会发生这种情况。一旦我能够使这个工作,我将尝试使其适用于N = *级别,我想这将涉及递归地创建更多的承诺。我在这里看到很多相关的问题,但不完全是我需要的。

    非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

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

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});
})

修改考虑使用.catch()代替第二个函数进行错误。 mpromise现在支持.catch()

答案 1 :(得分:1)

现在似乎找到了一个解决方案。

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 ..),根据文档,它应该表现得非常相似,除了返回一个promise。这是我必须使用Q promise api的一个原因,因为Document.populate不会像Model.populate那样返回一个承诺。我无法让Model.populate在没有常规节点样式回调的情况下工作,但是这个解决方案可以满足我的需求。至于N = *级别,我只是根据需要递归调用Q.ninvoke多次,扩展路径,我可以根据需要填充多个级别。

相关问题