Děkuji za podnět k napsání jasnějšího vysvětlení. Zde je úplný příklad s mými komentáři. Vyskytlo se několik chyb a nesrovnalostí, které jsem vyčistil. Toto bude používat příští vydání dokumentů.
Meteor.publish
je docela flexibilní. Není to omezeno na publikování existujících sbírek MongoDB klientovi:můžeme publikovat cokoli, co chceme. Konkrétně Meteor.publish
definuje množinu dokumentů které si klient může předplatit. Každý dokument patří k nějakému názvu kolekce (řetězci), má jedinečné _id
pole a pak má nějakou sadu atributů JSON. Jakmile se dokumenty v sadě změní, server odešle změny každému přihlášenému klientovi, aby byl klient stále aktuální.
Zde definujeme sadu dokumentů, nazvanou "counts-by-room"
, která obsahuje jeden dokument v kolekci s názvem "counts"
. Dokument bude mít dvě pole:roomId
s ID místnosti a count
:celkový počet zpráv v dané místnosti. Neexistuje žádná skutečná kolekce MongoDB s názvem counts
. Toto je pouze název kolekce, kterou náš server Meteor odešle klientovi a uloží na stranu klienta kolekce s názvem counts
.
K tomu potřebuje naše funkce publikování roomId
parametr, který přijde od klienta, a sleduje dotaz na všechny zprávy (definované jinde) v dané místnosti. Můžeme použít efektivnější observeChanges
formou pozorování dotazu zde, protože nebudeme potřebovat celý dokument, jen vědomí, že byl přidán nebo odebrán nový. Kdykoli je přidána nová zpráva s roomId
nás to zajímá, naše zpětné volání zvýší interní počet a poté publikuje nový dokument klientovi s tímto aktualizovaným součtem. A když je zpráva odstraněna, sníží počet a odešle klientovi aktualizaci.
Když poprvé zavoláme observeChanges
, nějaký počet added
zpětná volání proběhnou okamžitě pro každou zprávu, která již existuje. Budoucí změny se pak spustí při každém přidání nebo odebrání zpráv.
Naše funkce publikování také registruje onStop
handler k vyčištění, když se klient odhlásí (buď ručně, nebo při odpojení). Tento obslužný program odebere atributy z klienta a zruší spuštěné observeChanges
.
Funkce publikování se spustí pokaždé, když se nový klient přihlásí k odběru "counts-by-room"
, takže každý klient bude mít observeChanges
běží jeho jménem.
// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
var count = 0;
var initializing = true;
var handle = Messages.find({room_id: roomId}).observeChanges({
added: function (doc, idx) {
count++;
if (!initializing)
self.changed("counts", roomId, {count: count}); // "counts" is the published collection name
},
removed: function (doc, idx) {
count--;
self.changed("counts", roomId, {count: count}); // same published collection, "counts"
}
// don't care about moved or changed
});
initializing = false;
// publish the initial count. `observeChanges` guaranteed not to return
// until the initial set of `added` callbacks have run, so the `count`
// variable is up to date.
self.added("counts", roomId, {count: count});
// and signal that the initial document set is now available on the client
self.ready();
// turn off observe when client unsubscribes
self.onStop(function () {
handle.stop();
});
});
Nyní s tím na klientovi můžeme zacházet stejně jako s typickým předplatným Meteoru. Nejprve potřebujeme Mongo.Collection
který bude obsahovat náš dokument s vypočtenými počty. Protože server publikuje do kolekce s názvem "counts"
, předáme "counts"
jako argument pro Mongo.Collection
konstruktor.
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");
Pak se můžeme přihlásit k odběru. (Před vyhlášením sbírky se můžete přihlásit k odběru:Meteor zařadí příchozí aktualizace do fronty, dokud je nebude kam umístit.) Název předplatného je "counts-by-room"
a vyžaduje jeden argument:ID aktuální místnosti. Zabalil jsem to do Deps.autorun
takže jako Session.get('roomId')
změny, klient se automaticky odhlásí z počtu starých pokojů a znovu se přihlásí k počtu nových pokojů.
// client: autosubscribe to the count for the current room
Tracker.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
Konečně máme dokument v Counts
a můžeme ji použít stejně jako jakoukoli jinou kolekci Mongo na klientovi. Jakákoli šablona, která odkazuje na tato data, se automaticky překreslí, kdykoli server odešle nový počet.
// client: use the new collection
console.log("Current room has " + Counts.findOne().count + " messages.");