views:

40

answers:

2

I have a function that makes ajax GET request and based on the value returned sets one global JS variable. I use this variable (isCalculateTax in the code below) for further processing:

var isCalculateTax;

function setCalculateTaxValue(taxStatementId) {
 $.get('/taxstatements/calculatetax/' + taxStatementId, function (data) {
  isCalculateTax = data.isCalculateTax;
 });
}

$(document).ready(function () {
 // initially check the tax statements dropdown to see which one is selected
 // and set the isCalculateTax to the right value
 var taxStatementId = $('#taxStatements').val();
 setCalculateTaxValue(taxStatementId);
 enumerateDocumentItems(isCalculateTax);
});

My problem is that when enumerateDocumentItems() is called and executed the isCalculateTax is not yet updated from the AJAX GET request, so I receive unpredictable results.

How can I wait the necessary amount of time before executing enumerateDocumentItems() so that isCalculateTax will be correct?

A: 

Just call enumerateDocumentItems() from inside the $.get callback function, right after isCalculateTax is set.

Just make sure the UI makes sense in between.

Jochem
Inside the get() I can't because sometimes we want to do enumerateDocumentItems() but not always.
mare
+3  A: 

There are two ways to do this. First, you could change setCalculateTaxValue (and probably rename it) so that it accepts a callback that gets executed when the value is retrieved. You'd then pass enumerateDocumentItems as the callback. Alternately, and this is really going against the concept of asynchronicity, you can change it to use $.ajax and set the aSync option to false. I recommend the former.

var isCalculateTax; // no longer needed?

function updateTaxValue(taxStatementId,callback) { 
 $.get('/taxstatements/calculatetax/' + taxStatementId, function (data) {
  isCalculateTax = data.isCalculateTax;
  if (callback) {
      callback.call( taxStatementId, data.isCalculateTax ); 
  }
 }); 
} 

$(document).ready(function () { 
 // initially check the tax statements dropdown to see which one is selected 
 // and set the isCalculateTax to the right value 
 var taxStatementId = $('#taxStatements').val(); 
 updateTaxValue(taxStatementId,enumerateDocumentItems); 
});

Using the callback makes it a little more flexible than simply referencing the callback function directly. It will allow you to reuse the update code for more than one purpose if necessary.

tvanfosson
What if in some places we don't want to provide enumerateDocumentItems as callback? If we don't want it to be executed, can we just pass in null? see my comment to @Jochem..
mare
@mare - yes, this code checks to make sure that the callback is non-null before attempting to call it. Simply set the value to null: `updateTaxValue(taxStatementId,null)`.
tvanfosson
There's an error with your code: second argument to Function.prototype.apply must be an array[Break on this error] callback.apply(taxStatementId, data.isCalculateTax);
mare
@mare - sorry, it should have been `call`, not `apply`. I've fixed this. Or you could just wrap it in an array.
tvanfosson
@tvanfosson: perfect
mare