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

Meteor 发布和订阅

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

由 北公爵无欢 创建,路飞 最后一次修改 2016-08-12 发布和订阅发布(Publication)和订阅(Subscription)是 Meteor 的最基本最重要的概念之一,但是如果你是刚刚开始接触 Meteor 的话,也是有些难度的。这已经导致不少误解,比如认为 Meteor 是不安全的,或者说 Meteor 应用无法处理大量数据等等。人们起初会感觉这些概念很迷惑很大程度上是因为 Meteor 像变魔法一样替你做了很多事儿。尽管这些魔法最终看起来很有效,但是它们掩盖了后台真正做的工作(好像魔术一样)。所以让我们剥去魔法的外衣来看看究竟发生了什么。过去的日子首先,让我们回顾一下2011年之前,当 Meteor 还没有诞生的时候的老日子。比如说我们要建立一个简单的 Rails app。当用户来我们的站点,客户端(举例说浏览器)向我们的服务器端的 app 发送请求。App 的第一个任务就是搞清楚这个客户请求什么数据。这个可能是搜索结果的第12页、玛丽的用户信息、鲍勃的最新20条微博,等等等等。 你可以想想成为一个书店的伙计在书架之间帮你寻找你要的书。当正确的数据被找到,这个 App 的下一个任务就是把数据转换成好看的,人类可读的 HTML 格式(对于 API 而言是 JSON 串)。用书店来举例,那就相当于是把你刚买的书包好,然后装入一个漂亮的袋子。这就是著名的 MVC(模型-视图-控制器)模式中的视图部分。最终,App 把 HTML 代码送到客户端。这个 App 的任务也就交差了。它可以去买瓶啤酒然后等着下一个请求。Meteor 的方式让我们看看 Meteor 相对之下是多么的特别。正如我们看到的,Meteor 的关键性创新在于 Rails 程序只跑在服务器上,而一个 Meteor App 还包括在客户端(浏览器)上运行的客户端组件。推送数据库子集到客户端这就相当于书店的伙计不仅仅在书店里帮你找书,还跟你回家,每天晚上读给你听(这听起来怪怪的)。这种架构可以让 Meteor 做更多很酷的事情,其中一件主要的就是 Metoer 变得数据库无处不在。简单说,Meteor 把你的数据拿出一部分子集复制到客户端。这样后两个主要结果:第一,服务器不再发送 HTML 代码到客户端,而是发送真实的原始数据,让客户端决定如何处理线传数据。第二,你可以不必等待服务器传回数据,而是立即访问甚至修改数据(延迟补偿 latency compensation)。发布一个 App 的数据库可能用上万条数据,其中一些还可能是私用和保密敏感数据。显而易见我们不能简单地把数据库镜像到客户端去,无论是安全原因还是扩展性原因。所以我们需要告诉 Meteor 那些数据子集是需要送到客户端,我们将用发布功能来做这个事儿。让我们来回到 Microscope。这里是我们 App 数据库中的所有帖子:数据库中的所有帖子数据尽管实际上不存在但是我们还是假设我们的帖子中有几条因为言语不当被打了特殊标记的。我们需要把他们留在数据库中但是不希望让用户看到(发送去客户端)。我们第一个任务就是告诉 Meteor 那些数据我们要发送去客户端。我们告诉 Meteor 我们只发布没有打标记的帖子。排除做过标记的帖子这里是对应的代码,在服务器端代码中。// 在服务器端Meteor.publish('posts', function() { return Posts.find({flagged: false}); });这就保证客户端无论如何也无法看到打了标记的帖子了。这就是 Meteor App 如何做到安全性的:保证只发布你让这个当前用户看到的数据。DDP基本上我们可以把发布/订阅模式想象成为一个漏斗,从服务器端(数据源)过滤数据传送到客户端(目标)。这个漏斗的专属协议叫做 DDP(分布式数据协议 Distributed Data Protocol 的缩写)。如果想了解 DDP 的更多细节,可以通过看 Matt DeBergalis(Meteor 创始人之一)在 Real-time 大会上的讲演视频,或者来自 Chris Mather 的这个截屏视频,来学习关于这个概念更多的细节。订阅就算是我们想把打了标记的帖子也发送给客户端,我们也不能把成千上万的帖子一股脑都发出去。我们需要一个机制让客户端来确定那些子集是他们在某个特别时候特别需要的,这就是订阅这个功能的用途。通过 MiniMongo,客户端 MongoDB 的应用,你订阅的数据会被镜像到客户端。 举个例子,让我们现在浏览一下 Bob Smith 的个人页面,这里只会显示他的帖子。订阅 Bob 的帖子镜像到客户端首先,我们给发布功能加一个参数:// 在服务器端Meteor.publish('posts', function(author) { return Posts.find({flagged: false, author: author});});然后我们在客户端订阅这个发布时定义同一个参数。// 在客户端Meteor.subscribe('posts', 'bob-smith');这就是我们让 Meteor 程序在客户端能够具有可伸缩性:不去订阅全部数据,而是指选择你现在需要的数据去订阅。这样的话,你就可以避免消耗大量的客户端内存,无论服务器端的总数据量有多大。查找现在 Bob 的帖子恰巧涵盖了多个类别(比如:“JavaScript”、“Ruby”和“Python”)。也许我们仍然需要把 Bob 的所有帖子都装入内存,但是我们现在只想显示属于“JavaScript”类别的帖子。这就是“查找”的用途。在客户端选择一个数据子集正如我们在服务器上做的一样,我们用了 Posts.find() 函数来选择数据的子集:// 在客户端Template.posts.helpers({ posts: function(){ return Posts.find({author: 'bob-smith', category: 'JavaScript'}); }});现在我们应该明白订阅和发布机制了,让我们在深入了解一些常见的应用模式。自动发布如果你从头开始建立一个 Meteor 项目(比如,使用 meteor create 命令),系统会自动包含并启用一个叫做 autopublish 的包。让我们说说这个包是干什么的。autopublish 的目的是让 Meteor 应用有个简单的起步阶段,它简单地直接把服务器上的_全部数据_镜像到客户端,因此你就不用管发布和订阅了。自动发布那么这究竟是如何工作的呢?假设在服务器端我们有一个集合叫做 posts。自动发布包就会自动地把 Mongo 数据库中这个集合的所有的数据(帖子)发送到客户端的名为 ‘posts’ 的集合中(假设客户端的确有这样一个集合)。因此,如果你使用自动发布,你就不需要考虑发布。数据一致,而且事情变得十分简单。当然,这样的话会有一个明显的问题,就是你的所有数据都被缓存到所有用户的电脑中。基于这个原因,自动发布只在你起步阶段且还未考虑发布之前时使用。

[1] [2]  下一页


Meteor 发布和订阅