1

我正在自动订阅客户端上的集合。我的代码如下。我希望客户有更新的信息,但它永远不会更新。这个问题表现为一个按钮,除非我刷新页面,否则永远不会被消息替换。

实际上,我为“测试”集合拥有的一个文档应该在客户端将其 testCount 属性更新为 1,但除非我刷新页面,否则它永远不会发生。不应该更新吗?

未安装自动发布包。

在这一点上,我确信 Meteor 中存在错误,或者我只是不了解基本的东西。我即将安装meteor.js 的开发版本并弄清楚它或者干脆放弃,直到Meteor.js 可能真正起作用。:P

我的控制台日志:

Tests updated!
checking test
no test
Tests updated! Object {_id: "ea9f6002-74c7-4f37-9f10-0167b3b6f65a", testCount: 0}
checking test result
test.testCount 0

我的服务器日志:

$ meteor reset;meteor
Project reset.
[[[[[ ~/Dropbox/projects/sphela-game/sphela ]]]]]

Running on: http://localhost:3000/
inserting new test
Connecting test, getting initial data.
Test added do nothing { testCount: 0, _id: 'ea9f6002-74c7-4f37-9f10-0167b3b6f65a' }
Connecting test, getting initial data.
Test added do nothing { testCount: 0, _id: 'ea9f6002-74c7-4f37-9f10-0167b3b6f65a' }
Running test.
Updating test to 1.
Test ran. { testCount: 1, _id: 'ea9f6002-74c7-4f37-9f10-0167b3b6f65a' }
Test added do nothing { testCount: 1, _id: 'ea9f6002-74c7-4f37-9f10-0167b3b6f65a' }

我的html:

<head>   <title>Testing counts.</title> </head>

 <body>   {{> app}} </body>

 <template name="app">   
   {{#if testSuccess}}
     <h1>Test complete.</h1>
   {{else}}
     <button class="btn run-test">Run Test</button>
   {{/if}} 
 </template>

我的 JavaScript:

var Tests = new Meteor.Collection('tests');

if (Meteor.isClient) {
  Meteor.startup(function() {
    Session.set('testCount', 0)
    Meteor.subscribe('connect');
  });
  Template.app.testSuccess = function() {
    var test;
    console.log('checking test result');
    test = Tests.findOne();
    if (!test) {
      console.log('no test', test);
      return false;
    }
    console.log('test.testCount', test.testCount);
    return test.testCount > 0;
  };
  Template.app.events({
    'click .run-test': runTest
  });
  function runTest(event) {
    Meteor.call('runTest');
    Session.set('testCount', 1);
  }
  Meteor.autorun(function() {
    console.log('Tests updated!', Tests.findOne());
  });
  Meteor.autosubscribe(function() {
    Meteor.subscribe('test-results', Session.get('testCount'));
  });
}

if (Meteor.isServer) {
  Meteor.startup(function() {
    test = Tests.findOne({})
    if (!test) {
      test = {
        testCount: 0
      };
      console.log('inserting new test');
      test._id = Tests.insert(test);
    } else {
      console.log('startup reset');
      test.testCount = 0;
      Tests.update({_id:test._id}, test);
    }
  });

  Meteor.publish('connect', function() {
    var test_;
    console.log('Connecting test, getting initial data.');
    test_ = Tests.findOne({});
    this.set('tests', test_._id, test_);
    this.complete();
    this.flush();
  });

  Meteor.publish('test-results', function(test) {
    var handle;
    handle = Tests.find({testCount: test}).observe({
      changed: _.bind(function(test) {
        console.log('Test changed', test._id, test.testCount);
        this.set('tests', test._id, test);
        this.flush();
      }, this),
      added: _.bind(function(test) {
        console.log('Test added do nothing', test);
        this.flush();
      }, this)
    });
    this.complete();
    this.flush();
    this.onStop(function() {
      handle.stop();
    });
  });
  Meteor.methods({
    runTest: function() {
      var test;
      console.log('Running test.');
      test = Tests.findOne({});
      test.testCount = 1;
      console.log('Updating test to 1.');
      Tests.update({_id: test._id}, test);
      console.log('Test ran.', Tests.findOne());
    },
  });
  }
4

2 回答 2

3

流星的 Naomi 实际上在 Google Group 邮件列表上为我回答了我的问题。我的问题的要点是两个订阅/发布返回的冲突结果集,一个被忽略了。

这实际上在文档中,我错过了:

如果多个订阅为某个属性发送冲突的值(相同的集合名称、文档 ID 和属性名称),则客户端上的值将是客户端激活的第一个订阅的值。(即使它不是第一个发送重复属性的人。)

答案是不要在相互冲突的多个发布语句中返回结果集。我想避免发回相同的集合将有助于避免这种情况。

Naomi 的完整答案如下[1]:

您看到的行为涉及基于 Meteor 中的观察编写自定义发布者的一些细节。

在我看来,您所看到的是多个订阅如何工作的结果。这就是我认为正在发生的事情。初始发布,服务器发送下来“在收集测试中,有一个 id 为 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的对象,其中 testCount 为 0”会话变量计数为 0,因此我们订阅 test-results,其中 testCount 为 0。太好了,我们的本地版本的数据库已经认为,所有订阅都同意,无需更改。会话变量计数更新为 1。如果 testCount 为 1,则自动订阅并订阅测试结果。这意味着现在我们有两个发布者:'connect' 认为 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的 testCount 为 0(它永远不会更新,怎么会有不同的想法?“测试结果”得到“添加” 消息说 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的 testCount 为 1 (当你运行一个新的观察时,你会得到一个“添加”的消息,其中的所有内容。稍后,当事情发生匹配该光标更改) - 但它对添加的消息没有任何作用。看起来您期待的是“已更改”消息。这里的总体结果是,由于我们有一个发布者说 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的 testCount 为 0,并且没有发布者对此发表任何其他意见,因此客户认为 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 有测试计数为 0。与该光标匹配的事物发生变化时的消息)-但它对添加的消息没有任何作用。看起来您期待的是“已更改”消息。这里的总体结果是,由于我们有一个发布者说 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的 testCount 为 0,并且没有发布者对此发表任何其他意见,因此客户认为 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 有测试计数为 0。与该光标匹配的事物发生变化时的消息)-但它对添加的消息没有任何作用。看起来您期待的是“已更改”消息。这里的总体结果是,由于我们有一个发布者说 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的 testCount 为 0,并且没有发布者对此发表任何其他意见,因此客户认为 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 有测试计数为 0。

为确保客户端看到 testCount 为非 0,所有在集合中断言有关文档 ea9f6002-74c7-4f37-9f10-0167b3b6f65a 的任何发布者都必须说 testCount 为非 0,并具​​有适当的 set 和 flush 调用. 即使您在添加的观察回调中发送了 testCount 为 1 的消息,Meteor 也不保证客户端在订阅两个与文档值冲突的不同事物时看到的内容。

tl;dr 版本:观察游标在首次运行时为观察集中的所有内容获取一次添加的回调,即使这些项目已经在数据库中。当您有多个发布者在同一文档中发布相同的密钥时,客户端看到的版本将是其中之一,但如果发布者不同意,Meteor 不保证哪个版本。尽量不要让多个出版商对文件的内容产生不同意见,这只会造成混乱。

[1] https://groups.google.com/forum/?fromgroups=#!topic/meteor-talk/KBhXK6a44kY

于 2013-01-06T21:15:33.027 回答
1

这个问题表现为一个按钮,除非我刷新页面,否则永远不会被消息替换。

运行代码并单击按钮时,按钮将替换为:

测试完成。

控制台显示:

checking test result testcount.js:10
test.testCount 1 

将您的 javascript 文件粘贴到我的 IDE 后,我注意到一个错误;该方法的右大括号后的逗号runTest()。但据我所知,在运行测试时它没有负面影响。

于 2013-01-06T16:26:34.193 回答