Meteor での購読/公開で問題が発生しています。問題の範囲を絞り込むのに役立つ Meteor アプリの例を作成しました。
クライアントのサブスクリプションを介して渡されたパラメーターによってフィルター処理されたコレクションをサーバーに公開しています。このサブスクリプションは自動サブスクライブ内にあり、セッション変数を利用してサブスクリプションをリアクティブに更新します。
この特定のセッション変数の状態を変更すると、クライアントのコレクションが適切に更新されないか、少なくともそれが私が収集したものです。私はこれに一日中費やしましたが、私が管理しているコードに問題は見つかりませんでした。Meteor で適切な pub-sub をセットアップする方法を理解していないか、Meteor 内に問題があると思われます。
問題を再現するには、新しい Meteor プロジェクトを開始し、以下を使用します (試してみる場合は、必ず autopublish パッケージを削除してください)。
HTML (例: test.html):
<head>
<title>pubsubbug</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example showing possible bug in Meteor wrt pub-sub</h1>
<p><button name="showall">show all ({{showall}})</button></p>
<div style="float:left;width:400px;">
<h2>Notes:</h2>
<ul>
{{#each notes}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
<div style="float:left;">
<h2>Notes (copied):</h2>
<ul>
{{#each notes_copied}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</template>
JS (test.js など)
if (Meteor.is_client) {
Notes = new Meteor.Collection("notes_collection");
NotesCopied = new Meteor.Collection("notes_collection_copied");
Session.set("showall", false);
Meteor.autosubscribe(function () {
Meteor.subscribe("notes_subscription", Session.get("showall"), function () {
console.log("Notes count:", Notes.find().count());
});
Meteor.subscribe("notes_subscription_copied", Session.get("showall"), function () {
console.log("Bug? This isn't getting called.");
console.log("NotesCopied count:", NotesCopied.find().count());
});
});
Template.main.notes = function () {
return Notes.find();
};
Template.main.notes_copied = function () {
return NotesCopied.find();
};
Template.main.showall = function () {
return Session.get("showall");
};
Template.main.events = {
"click button[name='showall']": function (evt) {
Session.set("showall", !Session.get("showall"));
}
};
}
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
var getNotes = function (showall) {
if (showall) {
return Notes.find({}, {sort: {title: 1}});
} else {
return Notes.find({visible: true}, {sort: {title: 1}});
}
};
Meteor.publish("notes_subscription", function (showall) {
// By sending the Notes back with the same uuid as before, the
// client end seems to get confused:
return getNotes(showall);
});
Meteor.publish("notes_subscription_copied", function (showall) {
var notes = getNotes(showall);
var self = this;
// Copy notes into a new notes collection (see NotesCopied on client).
// By generating a new uuid, we don't get an issue with the notes
// on the client getting screwed up:
notes.forEach(function (note) {
var uuid = Meteor.uuid(); // note._id will cause same problem
self.set("notes_collection_copied", uuid, {title: note.title});
});
self.flush();
self.complete();
});
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1 (always visible)", visible: true});
Notes.insert({title: "Note #2 (always visible)", visible: true});
Notes.insert({title: "Note #3 (always visible)", visible: true});
Notes.insert({title: "Note #4 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #5 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #6 (only visible when showall true)", visible: false});
}
});
}
表示される内容の説明:
クリックすると、単にセッション変数 (showall) を true と false の間で切り替えるボタンがあります。
2 つのサブスクリプションが (自動サブスクライブ内に) 存在します。1 つはバグを例示するもので、もう 1 つは末尾に が付いています_copied
。これは、問題のコレクションが「コピー」され、新しい uuid が割り当てられたときに、結果が適切に表示されることを実証するためのテストです。この特定の情報をどうすればよいかわかりませんでした... 新しい uuid は必要ありません。
したがって、基本的に、 [すべて表示] ボタンを繰り返しクリックすると、最初の列の [メモ: ]に誤った結果が表示され、数回クリックしても何も表示されなくなります。
一方、毎回 uuid が再生成される2 列目のNotes (copied):は正しく表示されます。
これはバグですか?または、これを行う適切な方法はありますか?