【问题标题】:Meteor publish subscribe is not reactiveMeteor 发布订阅不是反应式的
【发布时间】:2014-07-09 11:25:42
【问题描述】:

当我更新集合时,我的客户端订阅例程没有刷新:

server/publish.js

Meteor.publish('decisions', function (decisionCursor) {
    return Decisions.find({ active: true }, { limit: 20, skip: decisionCursor });
});

Meteor.publish('decisionsToModerate', function (decisionCursor) {
    return Decisions.find({ active: false }, { sort: { createdAt: -1 }, limit: 1, skip: decisionCursor });
});

我为我的客户订阅了两个集合发布,当它获取所有数据时,它会创建一个包含一些我需要的东西的会话对象。

client/client.js

Meteor.startup(function () {
    SimpleSchema.debug = true;
    Deps.autorun(function () {
        Meteor.subscribe("decisions", Number(Session.get('decisionCursor')), function () {
            var decisionsVoted = {};
            Decisions.find({
                active: true
            }).forEach(function (decision) {
                var userVoted = Meteor.users.findOne({
                    "_id": Meteor.userId(),
                    "profile.votes.decision": decision._id
                }) != null ? Meteor.users.findOne({
                    "_id": Meteor.userId(),
                    "profile.votes.decision": decision._id
                }) : false;

                var ipVoted = Votes.findOne({
                    "ip": headers.get('x-forwarded-for'),
                    "votes.decision": decision._id
                }) != null ? true : false;
                if (ipVoted || userVoted)
                    decisionsVoted[decision._id] = {
                        voted: true,
                        blue: decision.blueTotal,
                        red: decision.redTotal,
                        bluePer: Math.round(decision.blueTotal * 100) / (decision.blueTotal + decision.redTotal),
                        redPer: Math.round(decision.redTotal * 100) / (decision.blueTotal + decision.redTotal)
                    };

            });
            Session.set('decisionsVoted', decisionsVoted);
        });
        Meteor.subscribe("decisionsToModerate", Number(Session.get('decisionCursor')));
    });
});

client/lib/environment.js

activeDecisions = function() {
    var decisions = Decisions.find({active: true});
    console.log(decisions.fetch().length);
    return decisions;
};
moderateDecisions = function() {
    return Decisions.find({active: false});
};

client/views/home/home.js

'click': function (event) {
    event.preventDefault();
    var decisionId = Session.get("selected_decision");
    var hasVoted = Session.get('decisionsVoted')[decisionId] ? Session.get('decisionsVoted')[decisionId].voted : false;

    Meteor.call("vote", decisionId, 'blue', hasVoted, function (error, result) {
        if (!error && result === true) {
            console.log(Session.get('decisionsVoted')[decisionId]); // UNDEFINED
        }
    });
},

当更新成功时,客户端订阅应该更新在我的会话对象中创建一个新对象,对吧?因为集合已更改,所以服务器中的发布已刷新...但它不会刷新,我评论 // UNDEFINED 而不是返回我的新对象正在返回 UNDEFINED

我不知道这是 Meteor 的行为还是我遗漏了一些东西...我尝试更新传递给发布方法 decisionCursor 的参数以强制更新,但没有发生任何事情 Session.set('decisionCursor', Session.get('decisionCursor'));

编辑:似乎如果我使用Session.set('decisionCursor', Session.get('decisionCursor') + 1);(请注意+1)它会刷新但不在结果函数内,如果我再次点击它会检测到添加了新对象...但我需要在结果函数中刷新它(在我的home.js 点击事件中)

【问题讨论】:

    标签: javascript node.js mongodb meteor


    【解决方案1】:

    This (excellent) article 可能会有所帮助。转述:

    ...在服务器上,Meteor 的反应仅限于 Meteor.publish() 函数返回的游标。这样做的直接后果是,与客户端不同,代码不会在数据发生变化时神奇地重新运行。

    【讨论】:

      【解决方案2】:

      Meteor.subscribe 的回调在服务器将订阅标记为就绪时调用,并且不是反应式上下文,因此当其依赖关系发生变化时它不会重新运行。 (反应式上下文不像闭包变量那样被继承,回调实际上在自动运行内部这一事实是无关紧要的。)你可能想要第二个autorun

      // original autorun
      Deps.autorun(function() {
        var decSubscription = Meteor.subscribe("decisions", Number(Session.get('decisionCursor')));
        Meteor.subscribe("decisionsToModerate", Number(Session.get('decisionCursor')));
      
        // Store the subscription handle in a session variable so that
        // the new autorun re-runs if we resubscribe
        Session.set("decSubscription", decSubscription);
      });
      
      // new autorun
      Deps.autorun(function() {
        // don't do anything if the subscription isn't ready yet
        var decCursor = Session.get("decSubscription");
        if (!decCursor.ready()) {
          Session.set("decisionsVoted", {});
          return;
        }
        var decisionsVoted = {};
        Decisions.find({active: true}).forEach(/* ... */);
        Session.set("decisionsVoted", decisionsVoted);
      });
      

      请注意,如果订阅尚未准备好,我们将跳过计算 decisionsVoted,否则当服务器发送初始结果集时,我们将在发送每个单独的文档后重新计算它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-18
        • 2016-11-29
        • 2017-11-30
        • 2013-11-18
        • 2016-03-07
        • 1970-01-01
        相关资源
        最近更新 更多