Meteor findOne查询在一个模板助手中返回未定义的结果.在其他模板助手中,同样的查询也能很好地工作

Meteor findOne query returns undefined in one template helper. In other template helpers, same query works well

本文关键字:查询 工作 很好 其他 findOne 一个 Meteor 未定义 返回 结果      更新时间:2023-09-26

假设我有一个名为GameStatus的Meteor集合。我有不同角色的用户,但我为所有用户发布GameStatus集合。我只是在server/publications.coffee 中使用以下内容

Meteor.publish 'gamestatus', ->
    GameStatus.find()

对于其中两个角色('S'和'B'),当我使用以下模板助手(在文件client/views/seller.coffeeclient/views/buyer.coffee中定义)时,我没有问题

currentRound: ->
    return GameStatus.findOne().currentRound

对于这些,我从未得到以下错误。

Uncaught TypeError: Cannot read property 'currentRound' of undefined 

但对于另一个角色("admin"),使用相同的模板助手(在文件client/views/admin.coffee中定义)会产生上面显示的Uncaught TypeError。如果我改为写:

currentRound: ->
    return GameStatus.findOne()?.currentRound

我有点理解为什么这样做。我认为,在加载页面时,集合首先不可用,然后才可用。但是,为什么上面显示的其他模板没有出现这种情况呢?

如果有人能帮忙澄清这一点,我将不胜感激。

我相信集合准备好的确切时间并不总是一致的,所以如果你想覆盖所有的基础,那么总是为集合还没有准备好的情况编写代码。

有一种快速而肮脏的方法来处理尚未准备好的集合,还有一种更复杂的解决方案,您可以在todos示例中找到。

快速而肮脏的解决方案会是这样的。

currentRound: ->
  gameStatusrecord = GameStatus.findOne();
  if(gameStatusRecord) 
    gameStatusRecord.currentRound

这会奏效的。在集合准备好之前,currentRound将返回null,您的模板将短暂呈现,并且可能只显示当前轮的空白。所以不是理想的用户体验,但也不是什么大不了的事。

对于更复杂的解决方案,您可以使用"ready"函数检查您订阅的集合是否已准备好进行查询。如果集合还没有准备好,您可以呈现一些其他模板,例如"加载",这可以保证在集合准备好之前不会调用currentRound辅助对象。

例如,在todos示例中,客户端订阅了todos.js:第24行的"lists"集合

var listsHandle = Meteor.subscribe('lists', function () {

然后在todos.js 的第80行为列表模板定义一个助手函数

Template.lists.loading = function () {
  return !listsHandle.ready();
};

然后,在todos.html第20行的lists模板中,除非listsHandle准备就绪,否则它不会尝试渲染任何模板。

<h3>Todo Lists</h3>
{{#if loading}}
  <div id="lists">Loading...</div>
{{else}}
  <div id="lists">
    {{#each lists}}
    <!--etc.-->