【问题标题】:Meteor Iron-Router: Wait for Subscription sequentialMeteor Iron-Router:等待订阅顺序
【发布时间】:2017-01-19 15:43:09
【问题描述】:

我的 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 本身提供的更方便的解决方案。您知道对此有更好的解决方案吗?

感谢您的回答!

【问题讨论】:

  • 难道不能只创建sub3,它采用与sub1相同的参数并返回sub1和sub2的数据吗?
  • 我不知道发布函数可以返回两个不同集合的结果?这是真的吗?
  • 是的,只返回一个数组docs.meteor.com/api/pubsub.html#Meteor-publish
  • 有趣的事情,非常感谢!

标签: meteor iron-router subscription


【解决方案1】:

发布复合包:

如果第二个订阅反应性地依赖于第一个数据集中的某些字段——并且如果存在多对多“加入”关联,则可能值得研究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 中的钩子非常有用,因为它们会为您处理很多事情。那么为什么不使用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);

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

【讨论】:

    【解决方案2】:

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

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

    这是我的代码 sn-p 可以工作,但奇怪的是我不得不将它包装在 1ms 超时中才能工作......

    ``` Router.route('/activity/:activityId', function (params) {

    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);

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

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

    你可以看到我在哪里订阅。

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

    【讨论】:

      猜你喜欢
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 2014-01-16
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多