2014-10-26 2 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. Я начинаю с 10 000 в обоих {{income_acct_budget}} и {{cashIn_acct_budget}}. Я меняю значение на 15 000 на стороне дохода, а на стороне cashIn все равно 10 000. Затем я меняю доходную сторону на 20 000, а теперь сторона cashIn составляет 15 000. cashIn всегда одно изменение. Что произошло здесь, когда я переместил процесс обновления на сервер? Как заставить их снова синхронизировать?

ответ

1

Проблема с кодом прямо сейчас, что ваши Meteor.call s являются асинхронными, но вы до сих пор считаете, что они синхронны: видеть, как после вызова первого Meteor.call вы сразу же начинаете пытаться получать обновленную коллекцию дохода итерируя над курсором и выполняя вычисление по его предполагаемому обновленному значению, но оно еще не обновлено!

Перемещая collection.update код на сервер, вы понимаете, что вы должны выполнить туда-обратно на сервер до того, как клиент может подтвердить, что сбор был действительно изменен: именно поэтому на стороне клиента Meteor.call являются асинхронными большинство из (клиентская сторона Meteor.call может быть синхронной, предоставляя заглушку метода, когда имеет смысл добиться компенсации задержки).

Ваша проблема заключается в том, что код, выполняемый сразу после вашего первого Meteor.call, предполагает, что коллекция (которая является подмножеством реплики мини-монго из существующей сборной памяти MongoDB) уже обновлена, но это будет не так, пока модификации сервера выполняются и отправляются обратно клиенту.

Я думаю, вы должны просто реорганизовать ваши вызовы из двух методов на один вызов на стороне сервера, который будет выполнять обновления синхронно, так как второй вызов метода не зависит от результата первого: в общем, он не делает смысл выполнять 2 вызова метода, если пользователь не выполнил 2 отдельных действия самостоятельно.

+0

Какое по-настоящему элегантное объяснение. Даже мне нужно было только один раз прочитать его, чтобы он имел для меня полный смысл. Я не читал что-то о Депах и совершенно смущен. Спасибо, что нашли время, чтобы написать отличный ответ! –

Смежные вопросы