嵌套的猫鼬填充了承诺
Posted
技术标签:
【中文标题】嵌套的猫鼬填充了承诺【英文标题】:Nested mongoose populate with promises 【发布时间】:2014-09-16 12:48:34 【问题描述】:我正在尝试填充我的模型,如下所示:
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);
);
);
几个小时以来,我一直在尝试使用 Promise 完成上述任务,即使在 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
我认为它应该如下工作:
-
exec() 返回一个 promise,我在第一次调用 then() 时开始处理它
如果 treeView 为假,我返回 doc,这被视为原始承诺的解决方案,因此第二个 then() 处理程序被调用。这确实发生了。
如果 treeView 为真,对 Model.populate 的调用将返回另一个承诺,该承诺也将在第二次调用 then() 时得到处理。
我收到此错误:
"status": "error",
"serverTimestamp": "2014-07-24T18:23:02.974Z",
"message": "\"function\" == \"undefined\""
我知道它会到达第二个 then() 的错误处理程序,因为我已经注销到控制台进行验证,但我无法弄清楚为什么会发生这种情况。一旦我可以让它工作,我将尝试让它在 N=* 级别上工作,我想这将涉及递归地创建更多的 Promise。我在这里看到了很多相关的问题,但不完全是我需要的。
非常感谢任何帮助。
【问题讨论】:
【参考方案1】:我能够使用从 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);
)
编辑考虑使用.catch()
而不是第二个函数来解决错误。 mpromise 现在支持.catch()
。
【讨论】:
【参考方案2】:现在似乎找到了解决方案。
Q.ninvoke(doc, 'populate',path: children.children)
.then(function(doc)
return res.json(doc);
,function(err)
return next(err);
);
对我来说奇怪的是我需要使用猫鼬 Document.populate 而不是 Model.populate(doc..) 根据文档应该表现得非常相似,除了一个返回一个承诺。这是我不得不使用 Q Promise api 的原因之一,因为 Document.populate 不会像 Model.populate 那样返回 Promise。如果没有常规的节点样式回调,我无法让 Model.populate 工作,但这个解决方案可以满足我的需要。至于 N=* 级别,我只是根据需要递归调用 Q.ninvoke 多次,扩展路径,我可以根据需要填充任意深度的级别。
【讨论】:
似乎这是使 document#populate 适合承诺链的唯一方法。谢谢。以上是关于嵌套的猫鼬填充了承诺的主要内容,如果未能解决你的问题,请参考以下文章