41 votes

Comment les messages-comte exemple dans le Météore docs de travail?

Avoir de la difficulté à la pleine compréhension de cet exemple tiré de la doc... j'ai essayé de courir un tas de différentes façons, donc j'ai pu observer comment il fonctionne, etc.

Comment vous abonner à cela? Peut-on inclure le côté client code nécessaire pour faire ce travail?

Est-il une collection intitulée messages-count? Est un Room une collection de messages? Peut-on inclure la collecte définitions dans l'exemple?

Des conseils sur la ce serait génial!

NOTE: ceci est le code comme il est apparu lors de cette question a d'abord été publié (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();
  });
});

52voto

debergalis Points 7802

Merci pour m'invite à écrire une explication plus claire. Voici un fuller exemple avec mes commentaires. Il y avait quelques bugs et incohérences que j'ai nettoyé. Suivant les docs de la libération de l'utilisation de ce.

Meteor.publish est tout à fait flexible. Il n'est pas limité à la publication existante MongoDB collections pour le client: nous pouvons publier tout ce que nous voulons. Plus précisément, Meteor.publish définit un ensemble de documents qu'un client peut s'abonner à. Chaque document appartient à une collection de nom (une chaîne), a un unique _id champ, puis a un certain ensemble de JSON attributs. Comme les documents dans l'ensemble le changement, le serveur va envoyer les modifications à chaque abonné du client, en gardant le client jusqu'à ce jour.

Nous allons définir un ensemble de documents ici, appelés "counts-by-room", qui contient un seul document dans une collection nommée "counts". Le document a deux champs: un roomId avec l'ID d'une chambre, et count: le nombre total de messages dans cette salle. Il n'y a pas de véritable collection MongoDB nommé counts. C'est juste le nom de la collection que notre serveur Meteor sera l'envoi vers le client, et le stockage dans une côté client collection nommée counts.

Pour ce faire, notre fonction publier prend un roomId paramètre qui viendra sur le client, et observe une requête de tous les Messages (défini par ailleurs) dans cette salle. Nous pouvons utiliser le plus efficace, observeChanges forme de l'observation d'une requête ici, puisque nous n'aurons pas besoin de l'intégralité du document, juste le fait de savoir qu'un autre a été ajouté ou supprimé. Chaque fois qu'un nouveau message est ajouté à l' roomId qui nous intéresse, notre rappel incrémente le décompte interne, puis publie un nouveau document pour le client avec la mise à jour de total. Et lorsqu'un message est supprimé, il décrémente le compteur et envoie au client la mise à jour.

Lorsque nous avons d'abord appel observeChanges, un certain nombre d' added rappels seront exécuter tout de suite, pour chaque message qui existe déjà. Les changements se déclenche lorsque les messages sont ajoutés ou supprimés.

Notre fonction publier enregistre également une onStop gestionnaire de nettoyer lors de la résiliation par le client (que ce soit manuellement ou lors de la déconnexion). Ce gestionnaire supprime les attributs de la part du client et des larmes en bas de l'exécution d' observeChanges.

Publier une fonction s'exécute à chaque fois qu'un nouveau client s'abonne "counts-by-room", de sorte que chaque client aura un observeChanges en cours d'exécution sur 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 typique Meteor abonnement. Tout d'abord, nous avons besoin d'un Meteor.Collection qui va contenir notre calculé compte de document. Depuis le serveur de publication dans une collection nommée "counts", nous passons "counts" que l'argument de l' Meteor.Collection constructeur.

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

Alors nous pouvons nous inscrire. (Il est possible de s'abonner avant de déclarer la collection: Meteor file d'attente de la future mise à jour jusqu'à il y a un endroit pour les mettre.) Le nom de l' abonnement est - "counts-by-room", et elle prend un argument: la salle de cours de l'ID. J'ai enroulé à l'intérieur d' Deps.autorun de sorte que, comme Session.get('roomId') modifications, le client se désabonner à partir de l'ancienne chambre du comte et de la réabonner à la nouvelle salle de comptage.

// client: autosubscribe to the count for the current room
Deps.autorun(function () {
  Meteor.subscribe("counts-by-room", Session.get("roomId"));
});

Enfin, nous avons le document en Counts et nous pouvons l'utiliser comme tout autre Mongo collection sur le client. Un modèle qui fait référence à ces données seront automatiquement redessiner à chaque fois que le serveur envoie un nouveau compte.

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

2voto

Pechkin Points 335

Comme Leonhardt Wille dit, l'inconvénient de cette solution est que meteor téléchargements de l'ensemble de la collection d'éléments de Mongo serveur juste pour les compter. Sa solution à gist.github.com/3925008 c'est mieux, mais le compteur ne sera pas mise à jour lorsque de nouveaux articles 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;
    }
}

0voto

Leonhardt Wille Points 355

Viens de trouver une solution au problème de l'auto.flush() envoie des milliers de mises à jour pour le client - il suffit d'utiliser _.anti-rebond lors du compte:

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()

Ce sera seulement de définir le nombre et le rincer à l'abonnement après 10ms n'y a aucun changement.

Grâce à @possibilités sur #meteor pour l'astuce.

0voto

Giant Elk Points 254

Qu'arriverait-il si la poignée.stop() a été commentée? Voir cet exemple n'est-il pas de travail parce que j'ai besoin de mettre onStop() à l'intérieur de cette fonction: checkSharedBy() ??

Meteor, Un à de Nombreuses Relations et ajouter un champ à côté client collection de Publier?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X