Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何处理Meteor中的动态订阅?_Meteor - Fatal编程技术网

如何处理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}});
    });
}