未找到类别,Meteor订阅

时间:2015-06-19 17:50:13

标签: node.js meteor

所以,我希望我的Meteor应用程序的Categories集合的内容始终可用于整个应用程序。我已经在某个地方读到了你可以通过将null指定为Meteor.publish函数的第一个参数(而不是名称)来完成此操作。

我使用了以下代码:

// Categories
Meteor.publish(null, function() {
    return Categories.find();
});

当我启动应用程序时,我在应用程序启动时收到以下错误(上面的代码段位于<app>/server/publications/global.js):

Exception from sub id undefined ReferenceError: Categories is not defined
  at [object Object].Meteor.publish.Meteor.users.find.fields.username [as _handler] (app/server/publications/global.js:8:12)
  at maybeAuditArgumentChecks (packages/ddp/livedata_server.js:1617:1)
  at [object Object]._.extend._runHandler (packages/ddp/livedata_server.js:950:1)
  at [object Object]._.extend._startSubscription (packages/ddp/livedata_server.js:769:1)
  at packages/ddp/livedata_server.js:1437:1

奇怪的是,它说,但该出版物似乎工作正常。 Mongol报告我的应用程序中可以使用Categories数据,并且没有其他地方可以发布该数据,因此它必须来自此调用。

有什么想法?我很困惑。我应该检查子类在返回之前是否存在类别吗?

2 个答案:

答案 0 :(得分:1)

添加到Matt K所说的内容(因为评论很糟糕,评论中的代码格式非常糟糕),这是一个可能的代码示例,它创建一个命名集合并维护连接客户端和连接客户端之间的数据同步服务器:

/lib/collections.js - 在服务器和客户端上运行

Categories = new Mongo.Collection('categories');

<强> /server/publications.js

Meteor.publish('categories', function() {
    return Categories.find();
});

/lib/router.js - (对于Iron Router并告诉所有路径在加载前等待my_collection订阅)

Router.configure({
  loadingTemplate: 'loading',
  waitOn: function() {
    return [
      Meteor.subscribe('categories')
    ];
  }
});

现在OP中你所做的是在服务器上创建一个未命名的集合,然后将其发布到所有连接的客户端:

http://docs.meteor.com/#/full/meteor_publish

<强> /lib/collections.js

Categories = new Mongo.Collection('categories');

<强> /服务器/出版物

Meteor.publish(null, function() {
    return Categories.find();
});

这样做只是将它从Categories.find();获得的所有数据以没有名称的集合的形式发送到客户端。由于它没有名称,因此没有直接的方法可以轻松告诉客户端何时成功订阅它,因为它没有waitOn可以查找的任何内容,但是有一个可能的解决方案.. < / p>

When is the "null" publish ready?

https://github.com/alanning/meteor-null-publish-test

但总的来说,向客户端发布null(未命名)集合是愚蠢的,因为你不知道每个客户端何时可以获得数据。如果可以的话,请避免使用我只使用我在本文上半部分描述的标准发布/订阅模式。

答案 1 :(得分:0)

在得到结果之前,Meteor正在做三件事......

  1. 定义变量Categories(大失败)
  2. 将光标放在Categories上,然后才能显示数据(这是IR的waitOn对此有用)
  3. 使用数据(您在眨眼间看到的内容)将光标返回Categories
  4. 你的应用程序的问题是它在尝试发布之前甚至不知道它是什么。然后,一旦它发现它是什么,它重新运行发布,一切都很好。这是一个app加载订单问题。确保您的收藏是在客户端上定义的。服务器(通常位于名为collections的文件夹中)。然后,确保您的发布功能位于名为server的文件夹中。这样做可以确保您的集合脚本在发布脚本之前运行。

    解决了这个问题之后,你的下一个问题就是防御性地编码。仅仅因为您总是订阅Categories并不意味着它总是可用,所以订阅需要时间。

    例如,这个:

    doc = Categories.findOne();
    if (!doc) return;
    ...
    return doc && doc.createdAt;
    

    不是这个:

    Categories.findOne().createdAt
    

    可以将相同的逻辑应用于发布功能以立即解决您的问题:

    return Categories && Categories.find();
    

    但我不推荐它,因为这是一个额外的几个CPU周期,你可以通过正确订购你的文档来避免。