Merci de m'avoir incité à écrire une explication plus claire. Voici un exemple plus complet avec mes commentaires. Il y avait quelques bugs et incohérences que j'ai nettoyés. La prochaine version de la documentation l'utilisera.
Meteor.publish
est assez souple. Cela ne se limite pas à publier des collections MongoDB existantes sur le client :nous pouvons publier tout ce que nous voulons. Plus précisément, Meteor.publish
définit un ensemble de documents auxquels un client peut souscrire. Chaque document appartient à un nom de collection (une chaîne), a un _id
unique champ, puis possède un ensemble d'attributs JSON. Au fur et à mesure que les documents de l'ensemble changent, le serveur enverra les modifications à chaque client abonné, en gardant le client à jour.
Nous allons définir ici un ensemble de documents, appelé "counts-by-room"
, qui contient un seul document dans une collection nommée "counts"
. Le document aura deux champs :un roomId
avec l'identifiant d'une pièce, et count
:le nombre total de messages dans cette salle. Il n'y a pas de vraie collection MongoDB nommée counts
. Il s'agit simplement du nom de la collection que notre serveur Meteor enverra au client et stockera dans un côté client collection nommée counts
.
Pour ce faire, notre fonction de publication prend un roomId
paramètre qui viendra du client, et observe une requête de tous les messages (définis ailleurs) dans cette salle. Nous pouvons utiliser le plus efficace observeChanges
forme d'observation d'une requête ici puisque nous n'aurons pas besoin du document complet, juste de savoir qu'un nouveau a été ajouté ou supprimé. Chaque fois qu'un nouveau message est ajouté avec le roomId
qui nous intéresse, notre rappel incrémente le décompte interne, puis publie un nouveau document pour le client avec ce total mis à jour. Et lorsqu'un message est supprimé, il décrémente le compte et envoie la mise à jour au client.
Lorsque nous appelons observeChanges
pour la première fois , un certain nombre de added
les rappels s'exécuteront immédiatement, pour chaque message qui existe déjà. Ensuite, les modifications futures se déclencheront chaque fois que des messages seront ajoutés ou supprimés.
Notre fonction de publication enregistre également un onStop
gestionnaire à nettoyer lorsque le client se désabonne (soit manuellement, soit lors de la déconnexion). Ce gestionnaire supprime les attributs du client et supprime les observeChanges
en cours d'exécution .
Une fonction de publication s'exécute chaque fois qu'un nouveau client s'abonne à "counts-by-room"
, ainsi chaque client aura un observeChanges
courir en son nom.
// 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();
});
});
Maintenant, sur le client, nous pouvons traiter cela comme un abonnement Meteor typique. Tout d'abord, nous avons besoin d'une Mongo.Collection
qui contiendra notre document de comptes calculés. Étant donné que le serveur publie dans une collection nommée "counts"
, on passe "counts"
comme argument de Mongo.Collection
constructeur.
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");
Ensuite, nous pouvons nous abonner. (Vous pouvez en fait vous abonner avant de déclarer la collection :Meteor mettra en file d'attente les mises à jour entrantes jusqu'à ce qu'il y ait un endroit où les mettre.) Le nom de l'abonnement est "counts-by-room"
, et il prend un argument :l'ID de la salle actuelle. J'ai enveloppé ceci dans Deps.autorun
de sorte que comme Session.get('roomId')
changements, le client se désabonnera automatiquement du décompte de l'ancienne salle et se réabonnera au décompte de la nouvelle salle.
// client: autosubscribe to the count for the current room
Tracker.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
Enfin, nous avons le document dans Counts
et nous pouvons l'utiliser comme n'importe quelle autre collection Mongo sur le client. Tout modèle faisant référence à ces données sera automatiquement redessiné chaque fois que le serveur enverra un nouveau décompte.
// client: use the new collection
console.log("Current room has " + Counts.findOne().count + " messages.");