Comment fonctionne l'exemple de compte-message dans Meteor?

J'ai du mal à comprendre cet exemple à partir des docs … J'ai essayé de l'exécuter de différentes façons pour pouvoir observer comment cela fonctionne, etc.

Comment vous souscrivez-vous? Peut-on inclure le code côté client nécessaire pour que cela fonctionne?

Existe-t-il une collection appelée nombre de messages-count ? Une Room une collection de messages? Pouvons-nous inclure les définitions de collection dans l'exemple?

Quelques conseils sur ce serait génial!

REMARQUE : c'est le code apparaissant lorsque cette question a été publiée (mai 2012). C'est plus simple maintenant.

 // server: publish the current size of a collection Meteor.publish("messages-count", function (roomId) { var self = this; var uuid = Meteor.uuid(); var count = 0; handle = Room.find({room_id: roomId}).observe({ added: function (doc, idx) { count++; self.set("messages-count", uuid, "count", count); self.flush(); }, removed: function (doc, idx) { count--; self.set("messages-count", uuid, "count", count); self.flush(); } // don't care about moved or changed }); // remove data and turn off observe when client unsubs self.onStop(function () { handle.stop(); self.unset("messages-count", uuid, "count"); self.flush(); }); }); 

Merci de m'avoir invité à rédiger une explication plus claire. Voici un exemple plus complet avec mes commentaires. Il y avait quelques bugs et des incohérences que j'ai nettoyés. La prochaine version de docs utilisera ceci.

Meteor.publish est assez flexible. Il ne se limite pas à la publication de collections MongoDB existantes auprès du 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 s'abonner. Chaque document appartient à un nom de collection (une chaîne), possède un champ _id unique, puis dispose d'un ensemble d'attributs JSON. À mesure que les documents dans la configuration changent, le serveur enverra les modifications à chaque client souscrit, en maintenant le client à jour.

Nous allons définir un ensemble de documents ici, appelé "counts-by-room" , qui contient un document unique dans une collection nommée "counts" . Le document aura deux champs: une roomId avec l'ID d'une pièce, et count : le nombre total de messages dans cette pièce. Il n'y a pas de véritable collection MongoDB nommée counts . Ce n'est que le nom de la collection que notre serveur Meteor va envoyer au client et le stockage dans une collection côté client nommée counts .

Pour ce faire, notre fonction de publication prend un paramètre roomId qui viendra du client et observera une requête de tous les Messages (définis ailleurs) dans cette pièce. Nous pouvons utiliser la forme d'observation plus efficace d'observation d'une requête ici car nous n'aurons pas besoin du document complet, juste la connaissance qu'une nouvelle a été ajoutée ou supprimée. Chaque fois qu'un nouveau message est ajouté avec la roomId nous sommes intéressés, notre rappel augmente le nombre interne, puis publie un nouveau document sur le client avec ce total mis à jour. Et lorsqu'un message est supprimé, il diminue le compte et envoie au client la mise à jour.

Lorsque nous appelons d'abord les observeChanges d' observeChanges , un certain nombre de rappels added fonctionneront tout à l' observeChanges , pour chaque message qui existe déjà. Ensuite, les changements futurs déclencheront chaque fois que des messages seront ajoutés ou supprimés.

Notre fonction de publication enregistre également un gestionnaire onStop pour nettoyer lorsque le client désinscrit (manuellement ou sur déconnexion). Ce gestionnaire supprime les attributs du client et déchire les observeChanges exécution.

Une fonction de publication s'exécute chaque fois qu'un nouveau client s'inscrit à "counts-by-room" , de sorte que chaque client aura une observeChanges cours d'exécution 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 tiendra notre document de compte calculé. Puisque le serveur publie dans une collection nommée "counts" , nous passons "counts" comme argument au constructeur Mongo.Collection .

 // client: declare collection to hold count object Counts = new Mongo.Collection("counts"); 

Ensuite, nous pouvons vous abonner. (Vous pouvez vous inscrire avant de déclarer la collecte: Meteor mettra en file d'attente les mises à jour entrantes jusqu'à ce qu'il y ait une place pour les mettre.) Le nom de l' abonnement est "counts-by-room" , et il faut un argument: l'ID de la pièce actuelle. Je l'ai enveloppé dans Deps.autorun afin que, lorsque Session.get('roomId') change, le client se désabonnera automatiquement du compte de la vieille salle et se résignera au compte de la nouvelle chambre.

 // 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 toute autre collection Mongo sur le client. Tout modèle qui fait référence à ces données sera automatiquement redessiné chaque fois que le serveur envoie un nouveau compte.

 // client: use the new collection console.log("Current room has " + Counts.findOne().count + " messages."); 

Comme Leonhardt Wille l'a déclaré, l'inconvénient de cette solution est que le météore télécharge toute la collection d'objets du serveur Mongo juste pour les compter. Sa solution chez gist.github.com/3925008 est meilleure, mais le compteur ne sera pas mis à jour lorsque de nouveaux articles seront insérés.

Voici ma solution réactive

Collections:

 Players = new Meteor.Collection("players"); PlayersCounts = new Meteor.Collection("players_counts") 

Serveur:

 Meteor.publish("players_counts", function(){ var uuid = Meteor.uuid() var self = this; var unthrottled_setCount = function(){ cnt = Players.find({}).count() self.set("players_counts", uuid, {count: cnt}) self.flush() } var setCount = _.throttle(unthrottled_setCount, 50) var handle = Meteor._InvalidationCrossbar.listen({collection: "players"}, function(notification, complete){ setCount(); complete(); }) setCount(); self.complete() self.flush() self.onStop(function(){ handle.stop(); self.unset("players_counts", uuid, ["count"]); self.flush(); }); }); 

Client:

 Meteor.subscribe("players_counts") Template.leaderboard.total = function(){ var cnt = PlayersCounts.findOne({}) if(cnt) { return cnt.count; } else { return null; } } 

Je viens de trouver une solution au problème où self.flush () envoie des milliers de mises à jour au client: utilisez simplement _.debounce lors du comptage:

 count = 0 throttled_subscription = _.debounce => @set 'items-count', uuid, count: count @flush() , 10 handle = Items.find(selector).observe added: => count++ throttled_subscription() removed: => count-- throttled_subscription() 

Cela ne créera que le compte et éliminera l'abonnement après 10 ms sans changement.

Merci à @possibilities sur #meteor pour l'indice.

Que se passerait-il si handle.stop () a été commenté? Voir cet exemple ne fonctionne-t-il pas parce que je dois mettre onStop () dans cette fonction: checkSharedBy () ??

Meteor, One to Many Relationship & ajouter le champ uniquement à la collection côté client dans Publish?