Meteor发布订阅不具备响应性。

3
我的客户端订阅程序在我更新集合时没有刷新:
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 的行为,或者我漏掉了什么......我尝试更新传递给 publish 方法的参数 decisionCursor 以强制更新,但什么也没发生: Session.set('decisionCursor', Session.get('decisionCursor')); 编辑:似乎如果我使用 Session.set('decisionCursor', Session.get('decisionCursor') + 1); (注意+1),它会被刷新,但不是在 result 函数内部,如果我再点击一次,它会检测到新对象已添加......但我需要它在 result 函数内部刷新(在我的home.js点击事件内部)
2个回答

7

这篇(非常好的)文章可能会有所帮助。简而言之:

在服务端,Meteor 的响应性仅限于 Meteor.publish() 函数返回的游标。这直接的后果是,与客户端不同,代码不会在数据发生变化时自动重新运行。


2

Meteor.subscribe的回调函数会在服务器标记订阅已准备好时被调用,它不是反应式上下文,因此当其依赖项发生更改时不会重新运行。(反应式上下文不像闭包变量一样继承,回调函数实际上在autorun内部并不重要。)你可能需要第二个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。否则,当服务器发送初始结果集时,我们将在发送每个单独文档后重新计算它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接