如何处理Meteor中的动态订阅?
我有一个发布,其范围取决于另一个集合的元素属性。在服务器上基本上是这样的:如何处理Meteor中的动态订阅?,meteor,Meteor,我有一个发布,其范围取决于另一个集合的元素属性。在服务器上基本上是这样的: Meteor.publish('kids', function (parent) { return Kids.find({ _id: { $in: parent.childrenIds } }); } 在上面的示例中,parent.childrenIds是一个数组,包含作为父对象的子对象的所有子对象的_id。在我想向父级添加新的子级之前,此操作可以正常工作: newKidId = Kids.insert({ n
Meteor.publish('kids', function (parent) {
return Kids.find({ _id: { $in: parent.childrenIds } });
}
在上面的示例中,parent.childrenIds
是一个数组,包含作为父对象的子对象的所有子对象的_id。在我想向父级添加新的子级之前,此操作可以正常工作:
newKidId = Kids.insert({ name: 'Joe' });
Parents.update({ _id: parentId }, { $push: { childrenIds: newKidId } });
这在服务器上为Kids
集合工作(即添加新的kid),并使用newKidId
更新父级的childrenIds
数组。但它不会更新上述“儿童”出版物(光标未更新/修改)。因此,客户端的Kids
集合不会更新(看起来对Kids
的更改已在客户端上回滚)
当客户端刷新时,所有发布都将停止/重新启动,新的kid(Joe)最终发布到客户端
有没有办法避免刷新客户端并强制重新发布
Kids
集合(理想情况下只将新的kid Joe发送给客户端)?Meteor中经常被误解的一点是服务器上没有反应。动态描述需要由客户端上的Deps.autorun
块处理。要执行此操作,请首先在项目目录中使用以下命令,确保未包括自动发布包:
$ meteor remove autopublish
其次,在客户端上设置自动运行块,如:
Meteor.startup(function(){
Meteor.subscribe('parents');
Deps.autorun(function() {
parent = Parents.findOne();
if (!parent) return;
Meteor.subscribe('kids', parent);
});
});
这将在父对象发生更改时拆除并设置订阅
您可以在中看到完整的工作示例。我认为如果已发布的查询依赖于第二个查询,则需要在发布函数中使用observe。不需要在客户端上自动运行Deps.autorun 见关于和的讨论 这是一些基于“房间计数”示例的代码
Meteor.publish( "kids", function(parent_id){
var self = this;
Parents.find({_id: parent_id}, { childrenIds: 1 }).observe({
added: function (document){
document.childrenIds.forEach( function(kidId){
self.added("kids", kidId, Kids.findOne( { _id: kidId}, {name: 1, _id: 1} ));
});
},
removed: function (oldDocument){
oldDocument.childrenIds.forEach( function(kidId){
self.removed("kids", kidId, Kids.findOne( { _id: kidId}, {name: 1, _id: 1} ));
});
},
changed: function (newDocument, oldDocument){
var oldLength = oldDocument.childrenIds.length;
var newLength = newDocument.childrenIds.length;
if (newLength > oldLength){
self.added("kids",
newDocument.childrenIds[newLength-1],
Kids.findOne( { _id: newDocument.childrenIds[newLength-1] }, {name:1, _id:1}) );
}
else{
self.removed("kids",
oldDocument.childrenIds[oldLength-1],
Kids.findOne( { _id: oldDocument.childrenIds[oldLength-1] }, {name:1, _id:1}) );
}
}
});
self.ready();
});
同时,有相当多的软件包用于处理反应式发布功能。我是《自述文件》的作者,在该文件包的末尾,我将我的文件包与其他几个文件包进行了比较:
将
家长
”查询字段仅限于儿童ID
,这一点很重要,这样自动运行
就不会对家长
文档进行任何其他更改而重新运行。感谢jagill的这一要点-它确实有效。现在,服务器代码确实依赖于客户端发送正确的parent
对象来确定parent.childrenIds
中的(最新)键。这是一个安全漏洞。您将如何在服务器上检查parent
是否确实已使用该特定的孩子进行了更新?我试着通过parent.\u id
(和改编《儿童》杂志),但它破坏了预期的行为(看看——我已经评论了我的编辑),这是一个单独的问题,我很乐意回答。但最好将其作为新问题发布,并接受/关闭此问题。完成-查看
Meteor.publish('kids', function (parentId) {
this.autorun(function (computation) {
var parent = Parents.findOne(parentId, {fields: {childrenIds: 1}});
return Kids.find({_id: {$in: parent.childrenIds}});
});
}