Dziękuję za skłonienie mnie do napisania jaśniejszego wyjaśnienia. Oto pełniejszy przykład z moimi komentarzami. Było kilka błędów i niespójności, które posprzątałem. Użyje tego następna wersja dokumentów.
Meteor.publish
jest dość elastyczny. Nie ogranicza się to do publikowania istniejących kolekcji MongoDB dla klienta:możemy opublikować wszystko, co chcemy. W szczególności Meteor.publish
definiuje zestaw dokumentów które klient może subskrybować. Każdy dokument należy do jakiejś nazwy kolekcji (ciąg), ma unikalny _id
pole, a następnie ma pewien zestaw atrybutów JSON. W miarę jak dokumenty w zestawie ulegną zmianie, serwer prześle zmiany do każdego subskrybowanego klienta, utrzymując klienta na bieżąco.
Zdefiniujemy tutaj zestaw dokumentów o nazwie "counts-by-room"
, który zawiera pojedynczy dokument w kolekcji o nazwie "counts"
. Dokument będzie miał dwa pola:roomId
z identyfikatorem pokoju i count
:całkowita liczba wiadomości w tym pokoju. Nie ma prawdziwej kolekcji MongoDB o nazwie counts
. To tylko nazwa kolekcji, którą nasz serwer Meteor będzie wysyłał do klienta i przechowywał po po stronie klienta kolekcja o nazwie counts
.
Aby to zrobić, nasza funkcja publikowania pobiera roomId
parametr, który będzie pochodził od klienta i obserwuje zapytanie dotyczące wszystkich wiadomości (zdefiniowanych w innym miejscu) w tym pokoju. Możemy użyć wydajniejszego observeChanges
forma obserwowania zapytania tutaj, ponieważ nie będziemy potrzebować pełnego dokumentu, tylko wiedza, że nowy został dodany lub usunięty. Za każdym razem, gdy dodawana jest nowa wiadomość z roomId
jesteśmy zainteresowani, nasze wywołanie zwrotne zwiększa wewnętrzny licznik, a następnie publikuje nowy dokument dla klienta z tą zaktualizowaną sumą. A kiedy wiadomość jest usuwana, zmniejsza licznik i wysyła klientowi aktualizację.
Kiedy po raz pierwszy wywołamy observeChanges
, pewna liczba added
wywołania zwrotne zostaną uruchomione od razu dla każdej wiadomości, która już istnieje. Następnie przyszłe zmiany będą uruchamiane za każdym razem, gdy wiadomości zostaną dodane lub usunięte.
Nasza funkcja publikowania rejestruje również onStop
handler do czyszczenia, gdy klient anuluje subskrypcję (ręcznie lub po rozłączeniu). Ten program obsługi usuwa atrybuty z klienta i usuwa działające observeChanges
.
Funkcja publikowania jest uruchamiana za każdym razem, gdy nowy klient subskrybuje "counts-by-room"
, więc każdy klient będzie miał observeChanges
działa w jego imieniu.
// 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();
});
});
Teraz na kliencie możemy potraktować to jak typową subskrypcję Meteor. Najpierw potrzebujemy Mongo.Collection
który będzie zawierał nasz dokument z obliczeniami. Ponieważ serwer publikuje w kolekcji o nazwie "counts"
, przekazujemy "counts"
jako argument do Mongo.Collection
konstruktor.
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");
Wtedy możemy się zapisać. (Właściwie możesz dokonać subskrypcji przed zadeklarowaniem kolekcji:Meteor będzie kolejkować nadchodzące aktualizacje, dopóki nie będzie miejsca na ich umieszczenie.) Nazwa subskrypcji to "counts-by-room"
i wymaga jednego argumentu:identyfikatora bieżącego pokoju. Umieściłem to w Deps.autorun
tak, że jako Session.get('roomId')
zmiany, klient automatycznie zrezygnuje z subskrypcji starego pokoju i ponownie zasubskrybuje nowy licznik.
// client: autosubscribe to the count for the current room
Tracker.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
Wreszcie mamy dokument w Counts
i możemy go używać tak jak każdej innej kolekcji Mongo na kliencie. Każdy szablon, który odwołuje się do tych danych, zostanie automatycznie przerysowany za każdym razem, gdy serwer wyśle nową liczbę.
// client: use the new collection
console.log("Current room has " + Counts.findOne().count + " messages.");