当前位置:K88软件开发文章中心编程语言JavaScriptMeteor → 文章内容

Meteor 高级发布机制

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 15:29:05

由 北公爵无欢 创建,路飞 最后一次修改 2016-08-12 高级发布机制目前你应该对发布和订阅交互模式有一个不错的掌握了。因此,我们废话少说,来看几个更高级的情景。多次发布一个集合在我们第一个关于发布的附录中,我们看到了一些更普遍的发布和订阅模式,同时我们学习了 _publishCursor 函数,如何让它们非常容易地实现在我们的站点上。首先,让我们回忆 _publishCursor 到底为我们做了什么:它将整理所有的文档以匹配一个给定的游标(cursor),并将它们推送至同名的客户端集合中。注意这与 publication 的名字是不关联的。这意味着我们可以用不止一个 publicaton 去连接任何集合的客户端与服务端版本。我们已经在分页章节用过这个模式,当我们在当前显示的帖子之外,再发布一个所有帖子的分页后的子集。另一个相似的用例是发布一大组文档的预览,和单个文档的全部信息:Meteor.publish('allPosts', function() { return Posts.find({}, {fields: {title: true, author: true}});});Meteor.publish('postDetail', function(postId) { return Posts.find(postId);});现在客户端订阅这两个发布,这 'posts' 集合来自于两个源渠道:来自第一个订阅的标题和作者姓名列表,和来自第二个订阅的单个帖子全部信息。你也许意识到了 postDetail 发布的帖子也被 allPosts 发布了(尽管只有它的部分属性)。但是,Meteor 会合并字段及确认没有重复的帖子,来处理数据重叠的问题。这是很棒的,因为现在当我们呈现帖子摘要列表时,我们正在处理的数据对象正好拥有我们需要显示的足够数据。但是,当我们呈现单个帖子时,我们有一切需要展示的数据。当然,在这种情况下,我们需要让客户端不要去期待所有帖子的所有字段都能都显示出来————这是一个常见的问题!注意你并没有改变文档属性的任何限制。你可以很好地在这两个发布中发布同样的属性,但是先后排序不同。Meteor.publish('newPosts', function(limit) { return Posts.find({}, {sort: {submitted: -1}, limit: limit});});Meteor.publish('bestPosts', function(limit) { return Posts.find({}, {sort: {votes: -1, submitted: -1}, limit: limit});});多次订阅一个发布我们已经看了如何多次发布同一个集合。事实证明你可以通过另一个模式来完成非常相近的结果:建立一个单一发布,却多次订阅它。在 Microscope 中,我们多次重复订阅 posts 发布,但 Iron Router 为我们设置并拆开每次的订阅。然而,没有理由我们不能同时进行多次订阅。举个例子,我们想要将最新的和最好的帖子同时载入内存:我们设定一个单一发布:Meteor.publish('posts', function(options) { return Posts.find({}, options);});并且我们多次订阅这个发布。事实上或多或少我们在 Microscope 里这样做了:Meteor.subscribe('posts', {submitted: -1, limit: 10});Meteor.subscribe('posts', {baseScore: -1, submitted: -1, limit: 10});接下来到底发生什么了?每个浏览器开启了两个不同的订阅,每个订阅连接到同个服务端的发布。每个订阅提供了不同的发布参数,但从根本上,每次一个(不同)文档子集从 posts 集合提取出来,并通过连接机制发送到客户端集合。你甚至可以用同样的参数订阅两次相同的发布。这个对很多处场景来说很难说有用,但这种弹性机制总有一天会有用的。单一订阅中的多个集合不像传统关系型数据库像 MySQL 使用 joins,NoSQL 数据库类似 Mongo 都是关于去规范化和嵌入。让我们看看它们是怎样在 Meteor 环境下工作的。让我们看一个具体的例子。我们已经对我们的帖子添加了评论,到目前为止,我们一直很愉快地只发布用户看的单个帖子的评论。但是,假设我们希望在首页中显示全部帖子的回复(记着这些帖子会在分页时被改变)。这个用例展示了一个很好的理由把评论嵌入帖子中,事实上这是促使我们来非规范化评论数量。当然我们可以总是嵌入评论到帖子中,并完全摒除 Comments 集合。但如同我们前面在去规范化章节看到的,我们将在分离的集合的操作中也会失去一些额外的好处。但是事实证明有一个涉及订阅的技巧,在保持分离集合的同时再嵌入我们的评论。让我们假定除了首页帖子列表之外,我们希望再订阅每个帖子的两个最新评论。使用独立的评论发布会很难完成这个要求,尤其在帖子列表受到某些限制时(比如说,最近的10个)。我们必须写一个发布,看起来像下面的代码:Meteor.publish('topComments', function(topPostIds) { return Comments.find({postId: topPostIds});});从性能角度来看这是个问题,因为这个发布将需要每次在 topPostIds 改变时消除及重新建立。有一个途径来解决这个问题。我们可以应用这个事实:就是我们不仅可以在每个集合上拥有多次发布,而且我们也可以在每个发布上拥有多个集合。Meteor.publish('topPosts', function(limit) { var sub = this, commentHandles = [], postHandle = null; // send over the top two comments attached to a single post function publishPostComments(postId) { var commentsCursor = Comments.find({postId: postId}, {limit: 2}); commentHandles[postId] = Mongo.Collection._publishCursor(commentsCursor, sub, 'comments'); } postHandle = Posts.find({}, {limit: limit}).observeChanges({ added: function(id, post) { publishPostComments(id); sub.added('posts', id, post); }, changed: function(id, fields) { sub.changed('posts', id, fields); }, removed: function(id) { // stop observing changes on the post's comments commentHandles[id] && commentHandles[id].stop(); // delete the post sub.removed('posts', id); } }); sub.ready(); // make sure we clean everything up (note `_publishCursor` // does this for us with the comment observers) sub.onStop(function() { postHandle.stop(); });});注意我们在这个发布中没有返回任何东西,因为我们自己手动给 sub 发送信息(通过 .added() 等方式)。所以我们不必通过返回一个游标来请求 _publishCursor 给我们来做这个动作。

[1] [2]  下一页


Meteor 高级发布机制