Meteor文档中的messages-count示例如何工作?
麻烦从文档充分理解这个例子…我试着运行它一堆不同的方式,所以我可以观察它是如何工作的,等等。
你如何订阅这个? 我们是否可以包含使这项工作所需的客户端代码?
有一个名为messages-count
的集合吗? Room
是一个消息的集合吗? 我们可以在示例中包含集合定义吗?
任何提示,这将是伟大的!
注意 :这是最初发布此问题时出现的代码(2012年5月)。 现在更简单了。
// 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(); }); });
感谢提醒我写一个更清楚的解释。 这是我的评论的一个更完整的例子。 我清理了一些错误和不一致的地方。 下一个文档发布将使用此。
Meteor.publish
相当灵活。 不限于将现有的MongoDB集合发布到客户端:我们可以发布任何我们想要的东西。 具体来说, Meteor.publish
定义了一组客户可以订阅的文档 。 每个文档都属于某个集合名称(一个string),具有唯一的_id
字段,然后具有一些JSON属性集合。 随着集合中的文档发生更改,服务器将把更改发送到每个订阅的客户端,使客户端保持最新状态。
我们将在这里定义一个名为"counts-by-room"
的文档集,其中包含名为"counts"
的集合中的单个文档。 该文档将有两个字段:一个房间ID与一个房间的ID,和count
:该房间的消息总数。 没有名为counts
真正的MongoDB集合。 这只是Meteor服务器将发送到客户端的集合的名称,并存储在名为counts
的客户端集合中。
为此,我们的发布函数需要一个来自客户端的roomId
参数,并观察该房间中所有消息(在别处定义)的查询。 我们可以在这里使用更有效的观察查询forms的观察查询,因为我们不需要完整的文档,只需要知道添加或删除了一个新的查询。 任何时候,随着我们感兴趣的roomId
添加新消息,我们的callback会增加内部计数,然后用更新的总数向客户端发布新文档。 当消息被删除时,它减less计数并向客户端发送更新。
当我们第一次调用observeChanges
,一些added
callback将立即运行,对于已经存在的每个消息。 那么每当添加或删除消息时,将来的更改都会触发。
我们的发布function还注册了一个onStop
处理程序来清理客户端取消订阅(手动或断开连接)。 这个处理程序从客户端删除属性,并将运行的observeChanges
。
每当新客户订阅"counts-by-room"
observeChanges
"counts-by-room"
,发布function就会运行,因此每个客户都将有一个observeChanges
运行”的observeChanges
。
// 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(); }); });
现在,在客户端,我们可以像对待典型的Meteor订阅一样对待它。 首先,我们需要一个Mongo.Collection
来存放计算的计数文件。 由于服务器正在发布到名为"counts"
的集合中,因此我们将"counts"
作为parameter passing给Mongo.Collection
构造函数。
// client: declare collection to hold count object Counts = new Mongo.Collection("counts");
那我们可以订阅。 (在声明集合之前,您可以实际订阅:meteor会将传入的更新排队,直到有一个放置它们的地方。) 订阅的名称是"counts-by-room"
,并且需要一个参数:当前房间的ID。 我把这个包装在Deps.autorun
所以当Session.get('roomId')
发生变化时,客户端将自动退出旧房间的计数并重新订阅新房间的计数。
// client: autosubscribe to the count for the current room Tracker.autorun(function () { Meteor.subscribe("counts-by-room", Session.get("roomId")); });
最后,我们已经获得了Counts
的文档,我们可以像使用客户端上的其他Mongo集合一样使用它。 只要服务器发送新计数,任何引用此数据的模板都将自动重新绘制。
// client: use the new collection console.log("Current room has " + Counts.findOne().count + " messages.");
正如Leonhardt Wille所说,这个解决scheme的缺点是meteor从Mongo服务器上下载整个项目集合来计算它们。 他的解决schemegist.github.com/3925008更好,但计数器插入新项目时不会更新。
这是我的react native解决scheme
类别:
Players = new Meteor.Collection("players"); PlayersCounts = new Meteor.Collection("players_counts")
服务器:
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(); }); });
客户:
Meteor.subscribe("players_counts") Template.leaderboard.total = function(){ var cnt = PlayersCounts.findOne({}) if(cnt) { return cnt.count; } else { return null; } }
刚刚发现self.flush()发送数千更新到客户端的问题的解决scheme – 计数时只使用_.debounce:
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()
这将只设置计数,并刷新订阅没有改变10毫秒后。
感谢#meteor提供的@possibilities提示。
如果handle.stop()被注释掉会发生什么? 看到这个例子是不工作的,因为我需要把onStop()放在这个函数里面:checkSharedBy()?
meteor,一对多关系&添加字段只发布到客户端collections?