如何明确取消订阅集合?

时间:2013-05-27 15:14:00

标签: meteor

我有一个带有大型“消息”集合的MongoDB;属于特定groupId的所有邮件。所以从这样的出版物开始:

Meteor.publish("messages", function(groupId) {
  return Messages.find({
    groupId: groupId
  });
});

和这样的订阅:

Deps.autorun(function() {
   return Meteor.subscribe("messages", Session.get("currentGroupId"));
});

这让我陷入困境,因为最初currentGroupId未定义,但是sill mongod将耗尽CPU来查找groupId == null的消息(虽然我知道没有)。

现在,我尝试按如下方式重写出版物:

Meteor.publish("messages", function(groupId) {
  if (groupId) {
    return Messages.find({
      groupId: groupId
    });
  } else {
    return {}; // is this the way to return an empty publication!?
  }
});

和/或将订阅重写为:

Deps.autorun(function() {
   if (Session.get("currentGroupId")) {
     return Meteor.subscribe("messages", Session.get("currentGroupId"));
   } else {
     // can I put a Meteor.unsubscribe("messages") here!?
   }
});

最初都有帮助。但是,只要currentGroupId再次未定义(因为用户导航到不同的页面),mongod仍然忙着为最后订阅的groupId重新查询数据库。那么如何取消订阅出版物,以便不再查询mongod?

4 个答案:

答案 0 :(得分:8)

根据文件,它必须是http://docs.meteor.com/#publish_stop

  

this.stop()   在发布函数内部调用。停止此客户的订阅;   不会在客户端上调用onError回调。

类似

Meteor.publish("messages", function(groupId) {
  if (groupId) {
    return Messages.find({
      groupId: groupId
    });
  } else {
    return this.stop();
  }
});

我想在客户端你可以在第一个例子中删除你的if / else之类的

Deps.autorun(function() {
   return Meteor.subscribe("messages", Session.get("currentGroupId"));
});

答案 1 :(得分:6)

我发现在.stop()调用返回的处理程序上调用.subscribe()函数更简单直接:

let handler = Meteor.subscribe('items');
...
handler.stop();

答案 2 :(得分:5)

只需在出版物中添加条件:

Meteor.publish("messages", function(groupId) {
  if (groupId) {
    return Messages.find({
      groupId: groupId
    });
});

并保留订阅:

Deps.autorun(function() {
  return Meteor.subscribe("messages", Session.get("currentGroupId"));
});

完成这项工作。

无需明确停止发布。最终,在完成当前运行的查询并发出另一个查询(似乎在系统中的某个位置排队)之后,不再查询MongoDB。

答案 3 :(得分:0)

在您的情况下,您应该停止autorun

documentation

中有一个例子

您的自动运行实际上是通过一个允许您停止它的参数调用的:

Deps.autorun(function (c) {
  if (! Session.equals("shouldAlert", true))
    return;

  c.stop();
  alert("Oh no!");
});