【问题标题】:Is there any way to know when an meteor subscription is 'valid'?有什么方法可以知道流星订阅何时“有效”?
【发布时间】:2012-05-29 07:06:53
【问题描述】:

如果我更改Session var 并通过autosubscribe 触发重新订阅,是否有任何回调机制等到“最新”数据从服务器关闭? [1]

如果您查看this gist,您会看到一些代码随着订阅的变化记录集合的内容。输出的相关部分:

at Subscribed; comments are: first post on #1 - second post on #1 
at Flushed; comments are: first post on #1 - second post on #1 
at Subscription complete; comments are: first post on #1 - second post on #1 - first post on #2 - second post on #2

因此,即使在 (a) 调用 .subscribe,(b) 调用 Meteor.flush (c) 位于 onReady 回调中,用于 .subscribe;集合中仍然存在陈旧数据,只有在第 3 种情况下才是“正确”数据。

我意识到响应式模板和.observe 最终会收到正确的数据,并且事情会“稳定”到正确的状态。但是有什么方法可以告诉我们我们还没有到达那里吗?

例如,大多数流星示例应用程序(以及我自己的应用程序)在从订阅的集合中添加和删除数据时都容易出现抖动(类似于 FOUC)。如果我们可以判断订阅正在“加载”,我们可以对此采取一些措施。

[1] 显然,服务器上的数据在不断变化,但正如您将在要点中看到的那样,我无法(没有超时)找到它甚至是正确的点。因此我在问题中使用了“有效”。

一个非常简单且常见的用例

采取制造的应用程序;当您第一次加载它时,似乎没有注册任何应用程序,直到数据通过网络传输并且应用程序突然出现。

原因是Meteor.subscribe 已被调用,但数据尚未传出。但是模板没有简单的方法来告诉数据是待处理的并且它应该显示一个“加载”模板。在madewith 中,它们实际上是在数据加载后做一些事情,但这是一个回调,因此打破了正常的流星做事方式(即反应式编码)。

如果能写出类似这样的东西会更好(IMO):

 {{unless apps_loaded}}{{> loading}}{{/unless}}

 Template.madewith.apps_loaded = function() { return !Apps.isComplete(); }

【问题讨论】:

    标签: meteor publish-subscribe


    【解决方案1】:

    有趣的问题。

    通知新订阅的正确位置是onReady 回调。请注意那里发生的日志记录总是包含您的新数据。检查 (a) 和 (b) 没有用,因为在调用 subscribe 和所有数据从服务器到达之间存在延迟。

    根本问题是,一旦刚刚停止的订阅的数据被删除,就没有等效的 onRemove 回调运行。此外,autosubscribe 故意在停止旧的 subs 之前启动新的 subs,以避免闪烁。

    真正的用例是什么?大多数时候这样的回调是不必要的,因为模板也可以将它们的查询限制在应该在范围内的数据上。在您的示例中,呈现 cmets 的模板帮助程序可能仅在会话中查询具有当前 post_id 的 cmets,因此数据库中存在额外的 cmets 并没有什么害处。 像这样的:

    Template.post.comments = function () {
      return Comments.find({post_id: Session.get('post_id')});
    };
    

    这允许使用比通用 autosubscribe 函数更复杂的策略,例如为用户查看的最后三个帖子订阅 cmets。或者,为每个帖子订阅前几个 cmets,然后仅在选择该帖子时单独订阅该帖子的完整 cmets。

    【讨论】:

    • 好的,在问题中添加了一个用例。我理解关于范围的观点,这是一个很好的;我想现在的问题是集合上是否存在(或者我们可以拥有?)isComplete() 函数。
    • 分页是真正的用例——我在上面发布了一个新问题。鉴于 Meteor 的当前状态,我看不到如何实现不闪烁的分页。
    【解决方案2】:

    我参加流星派对有点晚了,所以我不知道添加流星功能背后的历史,但为了完整起见,现在可以使用模板级订阅和 'subscriptionsReady ' :

    [js]
    Template.myTemplate.onCreated(function() {
      this.subscribe('myData');
    });
    
    [html]
    <template name="myTemplate">
      <h2>my Template</h2>
      {{#if Template.subscriptionsReady}}
        // code to loop/display myData
      {{else}}
        <p>Please wait..</p>
      {{/if}}
    </template>
    

    【讨论】:

      猜你喜欢
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      • 1970-01-01
      • 2015-05-02
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多