2014-10-26 80 views
0

我已經到達了我的第一個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,現在兌換方面是15,000。 cashIn總是一個變化。當我將更新過程移到服務器端時發生了什麼?我如何讓他們再次同步?

回答

1

與您的代碼的問題,現在的問題是,你的Meteor.call s爲異步的,但你仍然認爲他們是同步的:看看如何調用第一Meteor.call後,你立即開始試圖通過迭代一個遊標來獲取最新收入的收集和對其假定的更新值進行計算,但尚未更新!

通過移動collection.update代碼,你明白,你必須執行一個往返到服務器之前,客戶可以確認的是,集合確實修改了服務器:這就是爲什麼客戶端Meteor.call是異步的大部分時間(客戶端Meteor.call可以通過在實現延遲補償時有意義提供方法存根來同步)。

您的問題是代碼後立即執行你的第一個Meteor.call假設集合(這是實際的MongoDB服務器持續收集迷你蒙戈副本集)已經更新,但它不會是直到案件服務器修改被執行並被髮送回客戶端。

我認爲你應該簡單地將你的2個方法調用重構爲一個服務器端方法調用,它將同步執行更新,因爲第二個方法調用不依賴於第一個方法的結果:一般來說,它不會使如果用戶沒有單獨執行2個單獨的操作,則執行2個方法調用。

+0

多麼真正優雅的解釋。即使我只需要閱讀一次,因爲它對我來說完全有意義。我正在閱讀關於Deps的一些內容,並感到完全困惑。感謝您花時間撰寫這份優秀的回覆! – 2014-10-26 16:26:58

相關問題