【问题标题】:Weird behavior with Meteor subscription (client collection of wrong size)Meteor 订阅的奇怪行为(错误大小的客户端集合)
【发布时间】:2015-10-11 06:41:33
【问题描述】:

我有一个 Meteor 宠物项目,出于学习目的,我实现了传统的分页。这意味着,我只显示 Mongo 集合保存的所有记录的子集,并且我有“下一个”和“上一个”按钮,以及一个用于选择每页显示的结果数量的下拉菜单。

当我点击“上一个”的“下一个”时,有时我会遇到这个奇怪的故障,就像结果列表有点长一样。这可以在几分之一秒内看到,然后结果显示良好。

所以我检查了我的集合的大小,似乎 mini-mongo 集合的大小有时比它应该的大。这解释了这种效果,但我不知道为什么我会在我的代码中产生这种行为。

在服务器端,我通过以下方式提供我的收藏:

/** Publish all scenarios from the current user
@cursorStart, skip parameter
@recordLimit, limit parameter
@sortPreferences, object to sort the published cursor
*/
Meteor.publish('myScenarios', function(cursorStart, recordLimit, sortPreferences){
    var objSort = {};//object to sort the cursor
    console.log("Record limit# "+recordLimit);
    if(sortPreferences){
      objSort[sortPreferences.param] = sortPreferences.order;
    }else{
      objSort['createdAt'] = 1;
    }
    Mongo.Collection._publishCursor( 
      Scenarios.find({owner: this.userId }, {limit :recordLimit, skip : cursorStart, sort : objSort}), 
      this, 'myScenarios'); 
    this.ready();
}); 

这样,如果我想在每页显示 10 个结果,我只发布我收藏的 10 条记录,而不是将整个收藏发送给客户端。

在相应模板的事件中,当用户单击“下一个”或“上一个”按钮时,我将更新 session 变量来保存我想要显示的结果。例如

"click .next" : function(){
  var routeName = Router.current().route.getName();
  scenarioCount = scenarioTotalCount(routeName);//get the total size of this collection
  if(Number(Session.get('scenarioCursorStart')) + Number(Session.get('scenarioResultsPerPage')) < scenarioCount)
   Session.set('scenarioCursorStart', Number(Session.get('scenarioCursorStart'))+Number(Session.get('scenarioResultsPerPage')));
}

scenarioCursorStartskip 参数,用于知道我是否显示前 10 个结果,第二个 10(意思是 10 到 19)等等。scenarioResultsPerPage 将根据下拉列表的更改进行更新,当用户说他或她希望每页显示不同数量的结果时。也是涉及的另一个对象,我用它来指示我要按哪个字段对这些结果进行排序。无论如何,只有跳过参数scenarioCursorStart在点击“next”或“prev”按钮时被修改。

在客户端,我订阅了这个集合,例如

MyScenarios = new Mongo.Collection('myScenarios');
...
Deps.autorun(function(){
...
Meteor.subscribe('myScenarios', Number(Session.get('scenarioCursorStart')), Number(Session.get('scenarioResultsPerPage')), Session.get('scenarioCursorOrder'));  //scenarios of the current user

}

如果我 console.log 那里有我的 mini-mongo 集合的大小( console.log("列表大小:"+ MyScenarios.find().count()) )我在单击“下一步”(更新 skip 参数 scenarioCursorStart 但没有其他参数)时得到它,例如 10,然后是 20(或 12)和然后又是10。如果我 console.log 在服务器大小上 skiplimit 参数它们总是具有正确的值,所以我不会发布游标不同的大小或从我想要的不同记录形式开始。

我的理解是,我的订阅存在问题,因为集合的长度各不相同(而且并不总是加倍,这会更容易“诊断”。如果我每页请求 10 个结果,有时我会得到一个长度为 20,有时为 12 或 13。“故障”不一致)但服务器端的参数似乎没问题。

我完全不知道接下来要寻找什么或去哪里寻找。我将不胜感激任何帮助试图找到此问题的原因。也许我对 Meteor Pub-sub 机制有一个明显的问题,但无法弄清楚它没有按预期工作。

【问题讨论】:

  • 顺便说一句,我可以通过在渲染时添加 limitpatch(毕竟,我需要在客户端重新排序集合)但是我更愿意了解这种奇怪的 pub-sub 行为发生了什么以及我哪里出错了。快速修复 --> this.render('scenarioListTable', {data : { scenario : MyScenarios.find({}, {limit: Number(Session.get('scenarioResultsPerPage')),排序: objSort}) }} );

标签: mongodb meteor iron-router


【解决方案1】:

您可以在订阅新订阅之前尝试停止之前的订阅。

假设代码在您的 onRendered/onCreated 函数中,您可以尝试:

var instance = this;

Deps.autorun(function() {
    if( this.subscription != null ) {
        this.subscription.stop();
    }
    this.subscription = Meteor.subscribe('myScenarios',
        Number(Session.get('scenarioCursorStart')),
        Number(Session.get('scenarioResultsPerPage')),
        Session.get('scenarioCursorOrder')
    );
}

另外,我认为Deps 在几个版本前已更改为Tracker,您可能想在某个时候开始使用Tracker

【讨论】:

  • 我认为 Meteor.subscribe 不是反应式上下文,但我有一个“无限循环”的效果。在我的应用程序上不做任何事情,我可以看到那段代码被执行了好几次。我有我的 console.log 在那里我可以看到它不断地打印在控制台上,并且呈现的数据不断变化(具有 闪烁 效果)。我的 mini-mongo 集合的长度从 0(到 1 到 5 到 0 到 7...)到 10,等等。我可以使用second autorun,但尽管它消除了效果,但并不能解决我的问题。
猜你喜欢
  • 2012-08-26
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多