Meteor Iron-Router:等待订阅顺序

Meteor Iron-Router: Wait for Subscription sequential

我在 iron-router 中定义了以下路由:

    this.route("/example/:id", {
    name: "example",
    template: "example",
    action: function () {
        this.wait(Meteor.subscribe('sub1', this.params.id));
        this.wait(Meteor.subscribe('sub2', <<data of sub1 needed here>>));

        if (this.ready()) {
            this.render();
        } else {
            this.render('Loading');
        }
    }
});

我想在渲染我的实际模板之前等待 sub1 和 sub2。问题是我需要一段数据,它是 sub2 订阅的 sub1 结果的一部分。

如何按顺序等待订阅?这样我就可以将等待分成两步,等待我的第一个订阅完成。然后开始第二个订阅然后设置this.ready()渲染模板?

我想到的解决方法是使用 Reactive-Vars 进行订阅,而不使用 iron-router 提供的 .wait 和 .ready。但我想使用 iron-router 或 Meteor 本身提供的更方便的解决方案。你知道更好的解决方案吗?

感谢您的回答!

发布复合包:

如果第二个订阅反应性地依赖于第一个数据集中的某些字段——并且如果存在多对多 "join" 关联,则可能值得研究 reywood:publish-composite包裹:

它提供了一种干净简单的方法来管理具有层次关系的集合的关联订阅。

发表:

Meteor.publishComposite('compositeSub', function(id) {
    return {
        find: function() {
            // return all documents from FirstCollection filtered by 'this.params.id' passed to subscription
            return FirstCollection.find({ _id: id });
        },
        children: [
            find: function(item) {
                // return data from second collection filtered by using reference of each item's _id from results of first subscription
                // you can also use any other field from 'item' as reference here, as per your database relations
                return SecondCollection.find({ itemId: item._id });
            }
        ]
    }
});

订阅:

然后您可以使用以下方式在路由器中订阅:

Meteor.subscribe('compositeSub', this.params.id);

路由器挂钩:

作为建议,iron-router 中的 hooks 非常有用,因为它们会为您处理很多事情。那么为什么不使用 waitOn 钩子来整齐地管理 this.waitloading 状态呢?

this.route('/example/:id', {
  name: "example",
  template: "example",
  // this template will be rendered until the subscriptions are ready
  loadingTemplate: 'loading',

  waitOn: function () {
    // return one handle, a function, or an array
    return Meteor.subscribe('compositeSub', this.params.id);  
    // FYI, this can also return an array of subscriptions
  },

  action: function () {
    this.render();
  }
});

您可以使用configure选项为加载事件添加模板:

Router.configure({
    layoutTemplate: 'layout',
    loadingTemplate: 'loading'
});

关于相关评论的注释:

如果两个订阅仅依赖于传递给它的同一个 id 参数,您可以使用以下内容,如上面评论中 @abj27 所提到的——但是,以您的示例为例,情况似乎并非如此:

发表:

Meteor.publish("subOneAndTwo", function (exampleId) {
  check(exampleId, String);
  return [
    FirstCollection.find({ _id: exampleId });
    SecondCollection.find({ firstId: exampleId })
  ];
});

订阅:

Meteor.subscribe('subOneAndTwo', this.params.id);

因此,只需检查您需要什么并相应地使用解决方案。

https://github.com/kadirahq/subs-manager

使用此包,您可以为变量分配订阅。然后,您可以检查该变量的就绪状态。我刚刚开始工作......经过多年的努力理解。

这是我的代码片段,但奇怪的是我不得不将它包装在 1 毫秒的超时中才能工作...

``` Router.route('/activity/:activityId', 函数(参数) {

var params = this.params;

setTimeout(function(){

    var thePage = window.location.href.split("/");; 
    window.thePage = thePage[4];

    dbSubscriptionActivites.clear();
    window.thisDbSubscriptionActivites = "";
    window.thisDbSubscriptionActivites = dbSubscriptionActivites.subscribe("activityByPage", window.thePage);


    Tracker.autorun(function() {
        if(window.thisDbSubscriptionActivites.ready()) {

            dbSubscriptionComments.clear();
            window.thisDbSubscriptionComments = "";
            window.thisDbSubscriptionComments = dbSubscriptionComments.subscribe('fetchComments', "activity", Activities.findOne({})._id);

            BlazeLayout.render("activity"); 
            $('body').removeClass("shards-app-promo-page--1");

        }
    });

},1); // Must wait for DOM? 

}); ```

检查:window.thisDbSubscriptionActivites = dbSubscriptionActivites.subscribe("activityByPage", window.thePage);

我设置为 window 变量,但你可以做一个 const mySub = ...

然后,您稍后在自动运行功能中检查。

你可以看到我在做订阅的地方

我想我真的应该将 BlazeLayout 渲染移动到另一个 .ready() 检查评论。