只有在第二次更改后,Meteor才会​​对第一次更改做出反应

时间:2014-10-26 15:59:55

标签: meteor

我已经在我的第一个Meteor应用程序中达到了这一点,我可以将所有更新和插入移动到服务器端的Meteor.methods。我注意到的第一件事是我失去了"瞬间"一旦我这样做了反应。这就是我所拥有的:

HTML

<template name="income">
  {{#each accounts}}
    <tr>
      <td class="row1"><input type="text" maxlength="32" value="{{income_acct_name}}" id="income_acct_name{{_id}}"></td>
      <td class="row2" align="right"><input type="text" size="13" value="{{income_acct_budget}}" id="income_acct_budget{{_id}}"></td>
    </tr>
  {{/each}}
</template>

<template name="cashIn">
  {{#each accounts}}
    <tr>
    <td class="row1"><input type="text" size="18" value="{{cashIn_acct_name}}" id="cashIn_acct_name{{_id}}" readonly></td>
    <td class="row2_protected" align="right">{{cashIn_acct_budget}}</td>
    </tr>
  {{/each}}
</template>

的客户机/ income.js

Template.income.events ({
    'change td.row2': function(theEvent, theTemplate) {
        var changedRow = this._id;
        var budget = parseFloat(theTemplate.find('#income_acct_budget'+changedRow).value.replace(/[^\/\d.-]/g,''));
        var incomeCursor = income.find({"_id": changedRow});
            incomeCursor.forEach( function(acct) {
            total = acct.income_acct_total;
        });
        var achieved = 0;
        if (budget > 0)
        {
            achieved = Math.round(total/budget*100);
        }
        Meteor.call("incomeBudgetChange", changedRow, budget, achieved);

        // Update Total Income Budget
        var incomeCursor = income.find({"userID": Meteor.userId()});
        var budgetTotal = 0;
        incomeCursor.forEach( function(acct) {
            budgetTotal = budgetTotal + acct.income_acct_budget;
        });
        var achieved = 0;
        if (budgetTotal > 0)
        {
            achieved = Math.round(incomeTotal/budgetTotal*100);
        }
        Meteor.call('totalIncomeBudgetChange', totalIncomeID, budgetTotal, achieved);
    }
});

服务器/ income.js

Meteor.methods({
    'incomeBudgetChange': function(changedRow, budget, achieved){
        income.update (
            {"_id": changedRow},
            {$set: {"income_acct_budget": budget, "income_budget_achieved": achieved}}
        )
    },
    'totalIncomeBudgetChange': function(totalIncomeID, budgetTotal, achieved){
        cashIn.update (
            {"_id": totalIncomeID},
            {$set: {"cashIn_acct_budget": budgetTotal, "cashIn_budget_achieved": achieved}}
        )
    }
});

这里的问题是totalIncomeBudgetChange。我在{{income_acct_budget}}{{cashIn_acct_budget}}开始时都是10,000。我在收入方面将值更改为15,000,而cashIn方面仍为10,000。然后我将收入方面改为20,000,现在cashIn方面是15,000。 cashIn始终是一个变化。当我将更新过程移到服务器端时,这里发生了什么?如何让它们再次同步?

1 个答案:

答案 0 :(得分:1)

您的代码现在的问题是您的Meteor.call是异步的,但您仍然认为它们是同步的:请参阅调用第一个Meteor.call后如何立即开始尝试获取更新的收入通过遍历游标并对其假定的更新值执行计算来收集,但它尚未更新!

通过将collection.update代码移动到服务器,您了解到必须先执行到服务器的往返,然后客户端才能确认该集合确实已被修改:这就是客户端{{1在大多数情况下都是异步的(客户端Meteor.call可以通过在实现延迟补偿时提供方法存根来实现同步)。

您的问题是,在您的第一个Meteor.call之后立即执行的代码假定集合(它是实际MongoDB服务器持久收集的迷你mongo副本子集)已经更新,但它不会是在执行服务器修改并将其发送回客户端之前的情况。

我认为你应该简单地将你的2个方法调用重构为一个服务器端方法调用,它将同步执行更新,因为第二个方法调用不依赖于第一个调用的结果:通常,它没有意义如果用户没有自己执行2个单独的操作,则执行2个方法调用。