当前位置: 首页 > 知识库问答 >
问题:

了解Meteor发布/订阅

慕容文昌
2023-03-14

我已经设置了一个简单的应用程序,它显示了项目列表。我已经删除了自动发布包,所以我不会将所有内容发送给客户端。

 <template name="projectsIndex">    
   {{#each projects}}      
     {{name}}
   {{/each}}
 </template>

打开autopublish时,这将显示所有项目:

if Meteor.isClient
  Template.projectsIndex.projects = Projects.find()

移除后,我还必须执行以下操作:

 if Meteor.isServer
   Meteor.publish "projects", ->
     Projects.find()
 if Meteor.isClient
   Meteor.subscribe "projects"
   Template.projectsIndex.projects = Projects.find()

那么,说客户端的find()方法只搜索从服务器端发布的记录,准确吗?它一直在绊倒我,因为我觉得我应该只调用一次。

共有3个答案

翟善
2023-03-14

这里的基本经验法则是发布和订阅的变量名称在客户端和服务器端应该相同。

Mongo DB和客户端上的集合名称应相同。

假设我正在使用publish和subscribe来订阅名为employees的集合,那么代码如下所示

在这里,使用var关键字是可选的(使用此关键字使集合成为此文件的本地集合)。

CollectionNameOnServerSide = new Mongo.Collection('employees');   

Meteor.publish('employeesPubSub', function() { 
    return CollectionNameOnServerSide.find({});     
});
CollectionNameOnClientSide = new Mongo.Collection('employees');
var employeesData = Meteor.subscribe('employeesPubSub');

Template.templateName.helpers({
  'subcribedDataNotAvailable' : function(){
        return !employeesData.ready();
    },
   'employeeNumbers' : () =>{
       CollectionNameOnClientSide.find({'empId':1});
  }
});

在这里,我们可以使用subcribedDataNotAvailable帮助器方法来了解客户端的数据是否准备就绪,如果数据准备就绪,则使用EmployeeNumber帮助器方法打印员工编号。

<TEMPLATE name="templateName">
{{#if subcribedDataNotAvailable}}
   <h1> data loading ... </h1>
 {{else}}
  {{#each employeeNumbers }}
     {{this}}
  {{/each}}
 {{/if}}
<TEMPLATE>
薛高澹
2023-03-14

是的,客户端find()只返回客户端上以Minimongo表示的文档。来自文档:

在客户端上,会创建一个Minimongo实例。Minimongo本质上是纯JavaScript中Mongo的内存中非持久性实现。它充当一个本地缓存,只存储该客户端正在使用的数据库的子集。客户端上的查询(find)直接从该缓存中提供,而无需与服务器对话。

正如您所说,publish()指定客户端将拥有哪些文档。

边翔宇
2023-03-14

收藏、出版物和订阅是Meteor的一个棘手领域,文档可以更详细地讨论这些领域,以避免经常出现混淆,有时混淆的术语会加剧混淆。

以下是SachaGreif(DiscoveryMeteor的合著者)在一张幻灯片中解释出版物和订阅:

要正确理解为什么需要多次调用search(),您需要了解Meteor中的集合、发布和订阅是如何工作的:

>

  • 您可以在MongoDB中定义集合。还没有涉及流星。这些集合包含数据库记录(Mongo和Meteor都称为“documents”,但“document”比数据库记录更通用;例如,更新规范或查询选择器也是文档-JavaScript对象包含字段:值对)。

    然后在Meteor服务器上定义集合

    MyCollection = new Mongo.Collection('collection-name-in-mongo')
    

    这些集合包含来自MongoDB集合的所有数据,您可以对它们运行MyCollection.find({...}),这将返回一个游标(一组记录,以及遍历它们并返回它们的方法)。

    此光标(大多数情况下)用于发布(发送)一组记录(称为“记录集”)。您可以选择仅发布这些记录中的某些字段。客户端订阅的是记录集(而不是集合)。发布由发布函数完成,该函数在每次新客户端订阅时都会调用,并且可以使用参数来管理要返回的记录(例如,用户id,仅返回该用户的文档)。

    在客户端上,您有部分镜像服务器中的一些记录的最小集合。“部分”是因为它们可能只包含一些字段,而“一些记录”是因为您通常只想向客户端发送它需要的记录,以加快页面加载,并且只发送它需要并有权访问的记录。

    Miniongo本质上是Mongo在纯JavaScript中的内存中、非持久实现。它用作本地缓存,仅存储此客户端正在使用的数据库的子集。客户端上的查询(查找)直接在此缓存中提供,无需与服务器对话。

    这些Minimongo集合最初为空。他们由

    Meteor.subscribe('record-set-name')
    

    电话。请注意,要订阅的参数不是集合名称;它是服务器在发布调用中使用的记录集的名称。调用subscribe()将客户端订阅到一个记录集-服务器集合中的记录子集(例如,最近的100篇博客文章),每个记录中包含所有或一个子集字段(例如,仅标题和日期)。Minimongo如何知道将传入记录放入哪个集合?集合的名称将是发布处理程序添加的、更改的和删除的回调中使用的集合参数,或者如果缺少这些回调(大多数情况下都是这样),它将是服务器上MongoDB集合的名称。

    这就是Meteor使事情变得非常方便的地方:当您在客户端上修改Minimongo集合中的记录(文档)时,Meteor将立即更新依赖于它的所有模板,并将更改发送回服务器,服务器将反过来将更改存储在MongoDB中,并将其发送给订阅了包含该文档的记录集的相应客户端。这被称为延迟补偿,是Meteor的七个核心原则之一。

    您可以有一堆订阅来提取不同的记录,但是如果它们来自服务器上的同一个集合,则它们最终都将在客户端的同一个集合中,基于它们的_id。这没有解释清楚,但Meteor文档暗示了这一点:

    当您订阅记录集时,它会告诉服务器将记录发送到客户端。客户端将这些记录存储在本地Minimongo集合中,其名称与发布处理程序添加的、更改的和删除的回调中使用的集合参数的名称相同。Meteor将对传入属性进行排队,直到您声明Mongo。客户端上具有匹配集合名称的集合。

    没有解释的是,如果您没有明确地使用添加的、更改的和删除的处理程序,或者根本没有发布处理程序(大多数情况下都是这样),会发生什么情况。在这种最常见的情况下,collection参数(毫不奇怪)取自您在步骤1中在服务器上声明的MongoDB集合的名称。但这意味着您可以使用不同的名称进行不同的发布和订阅,并且所有记录最终都将位于客户端上的同一个集合中。在顶级字段级别,Meteor会在文档之间执行集合合并,以便订阅可以重叠-发布功能将不同的顶级字段并排发送到客户端,在客户端上,集合中的文档将是两组字段的合并。

    您有一个BlogPosts集合,您在服务器和客户端上以相同的方式声明它,即使它做不同的事情:

    BlogPosts = new Mongo.Collection('posts');
    

    在客户端上,博客帖子可以从以下位置获取记录:

    >

  • 订阅最近10篇博客文章

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    

    对当前用户帖子的订阅

    // server
    Meteor.publish('posts-current-user', function publishFunction() {
      return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10});
      // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId
    }
    Meteor.publish('posts-by-user', function publishFunction(who) {
      return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10});
    }
    
    // client
    Meteor.subscribe('posts-current-user');
    Meteor.subscribe('posts-by-user', someUser);
    

    订阅最受欢迎的帖子

    所有这些文档都来自MongoDB中的博客帖子集合,通过服务器上的博客帖子集合,最终进入客户端的博客帖子集合。

    现在,我们可以理解为什么需要多次调用find(),第二次是在客户端上,因为来自所有订阅的文档最终将位于同一个集合中,并且只需要获取您关心的文档。例如,要获取客户端上的最新帖子,只需从服务器镜像查询:

    var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    

    这将返回一个光标到客户端迄今为止收到的所有文档/记录,包括顶部帖子和用户帖子。(谢谢杰弗里)。

  •  类似资料:
    • 本文向大家介绍meteor 基本订阅和发布,包括了meteor 基本订阅和发布的使用技巧和注意事项,需要的朋友参考一下 示例 首先,删除autopublish。autopublish自动将整个数据库发布到客户端,因此无法看到发布和订阅的效果。 删除autopublish: 然后,您可以创建出版物。下面是一个完整的示例。            

    • 我在服务器上有这个发布 在客户端上,我想订阅。但我怎样才能接触到背后的数据呢?我尝试了以下内容: 并找到方法 我做错了/理解错了,但我认为我很接近。谢谢

    • 简介 Redis 的列表类型键可以用来实现队列,并且支持阻塞式读取,所以 Redis 能够非常容易的实现一个高性能的优先队列。同时在更高层面上,Redis 还支持“发布/订阅”的消息模式,可以基于此构建一个聊天系统。 发布示例 发布(Publish)即将消息发布到频道中。示例代码: // 发送消息 Redis::publish('chan-1', 'Hello, World!'); // 发送消息

    • 本文向大家介绍meteor 了解构建进度,包括了meteor 了解构建进度的使用技巧和注意事项,需要的朋友参考一下 示例 有时构建所需的时间比预期的长。您可以设置一些环境变量,以更好地了解构建过程中发生的情况。 <n>毫秒数在哪里。花费时间超过此时间的任何进程都将被记录。 Linux / OSX示例 Windows示例            

    • 我有本出版物 但我得到了这个错误

    • 主要内容:发布/订阅流程,常用命令汇总,基本命令应用Redis PubSub 模块又称发布订阅者模式,是一种消息传递系统,实现了消息多播功能。发布者(即发送方)发送消息,订阅者(即接收方)接收消息,而用来传递消息的链路则被称为  channel。在 Redis 中,一个客户端可以订阅任意数量的 channel(可译为频道)。 消息多播:生产者生产一次消息,中间件负责将消息复制到多个消息队列中,每个消息队列由相应的消费组进行消费,这是分布式系统常用的