1

クライアントのコレクションを自動購読しています。私のコードは以下の通りです。クライアントが情報を更新することを期待していますが、更新されることはありません。この問題は、ページを更新しない限り、ボタンがメッセージに置き換えられないことで明らかになります。

実際、「Tests」コレクション用に持っている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

meteor の Naomi が、実際に Google グループのメーリング リストで私の質問に答えてくれました。私の問題の要点は、2 つの subscribe/publish が競合する結果セットを返し、1 つが無視されたことです。

これは実際にはドキュメントにあり、見逃しました:

複数のサブスクリプションが属性に対して競合する値 (同じコレクション名、ドキュメント ID、および属性名) を送信する場合、クライアントの値は、クライアントがアクティブ化した最初のサブスクリプションの値になります。(重複した属性を送信するのが最初でなくても。)

答えは、互いに競合する複数の発行ステートメントで結果セットを返さないことです。同じコレクションを返送しないようにすることで、これを回避できると思います。

ナオミの完全な回答は以下のとおりです[1]:

あなたが目にしている動作は、Meteor の観察に基づいてカスタム パブリッシャーを記述することの詳細に入ります。

あなたが見ているのは、複数のサブスクリプションがどのように機能するかの結果であるように私には思えます。これが私が起こっていると思うことです。最初のパブリッシュでは、サーバーが「コレクション テストで、id が ea9f6002-74c7-4f37-9f10-0167b3b6f65a で、testCount が 0 のオブジェクトがあります」と送信します。データベースのローカル バージョンは、すべてのサブスクリプションが同意し、変更は不要であると既に考えています。セッション変数カウントは 1 に更新されます。自動サブスクライブが実行され、テスト結果へのサブスクライブは testCount が 1 でした。これは、2 つのパブリッシャーが実行されていることを意味します。更新されることはありませんが、どうすれば別の考え方ができるのでしょうか? ea9f6002-74c7-4f37-9f10-0167b3b6f65a と言うメッセージの testCount は 1 です (新しい監視を実行すると、その中のすべてについて「追加」メッセージが表示されます。そのカーソルの変化に一致します) -- しかし、追加されたメッセージには何もしません。代わりに「変更された」メッセージを期待していたようです。ここでの全体的な結果は、ea9f6002-74c7-4f37-9f10-0167b3b6f65a の testCount が 0 であると言っている 1 つのパブリッシャーがあり、それについて他に何も言っていないパブリッシャーがいないため、クライアントは ea9f6002-74c7-4f37-9f10-0167b3b6f65a が0 の testCount。そのカーソルに一致するものが変更されたときにメッセージが表示されます) -- しかし、追加されたメッセージには何もしません。代わりに「変更された」メッセージを期待していたようです。ここでの全体的な結果は、ea9f6002-74c7-4f37-9f10-0167b3b6f65a の testCount が 0 であると言っている 1 つのパブリッシャーがあり、それについて他に何も言っていないパブリッシャーがいないため、クライアントは ea9f6002-74c7-4f37-9f10-0167b3b6f65a が0 の testCount。そのカーソルに一致するものが変更されたときにメッセージが表示されます) -- しかし、追加されたメッセージには何もしません。代わりに「変更された」メッセージを期待していたようです。ここでの全体的な結果は、ea9f6002-74c7-4f37-9f10-0167b3b6f65a の testCount が 0 であると言っている 1 つのパブリッシャーがあり、それについて他に何も言っていないパブリッシャーがいないため、クライアントは ea9f6002-74c7-4f37-9f10-0167b3b6f65a が0 の testCount。

クライアントが testCount が 0 ではないことを確認できるようにするには、コレクション内のドキュメント ea9f6002-74c7-4f37-9f10-0167b3b6f65a について何かをアサートするすべてのパブリッシャーが、適切な set および flush 呼び出しを使用して、testCount が 0 ではないことを示す必要があります。 . オブザーブの追加されたコールバックで testCount が 1 であるというメッセージを送信したとしても、Meteor は、ドキュメントの値に関して競合する 2 つの異なるものにサブスクライブしたときにクライアントが見るものについて何も保証しません。

tl;dr バージョン: カーソルを監視すると、項目が既にデータベースにあった場合でも、最初に実行されるたびに、監視対象セット内のすべてに対して追加されたコールバックが 1 回取得されます。複数のパブリッシャーが同じドキュメントで同じキーを公開している場合、クライアントが見るバージョンはそのうちの 1 つになりますが、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に貼り付けた後、1つのエラーに気づきました。メソッドの閉じ中括弧の後のコンマrunTest()。しかし、私が見る限り、テストを実行しても悪影響はありませんでした。

于 2013-01-06T16:26:34.193 に答える