Reputation: 5361
I may be doing something very silly here. Basically a user can have multiple "sites" and for each site we have to run some calculations to come up with a total. We have a php page which does these calculations which we can call calculate.php
. It returns a string ex: 50
which we then parse into a float in JS. So here's what I'm trying to do: get the total of all of the numbers outputted by calculate.php.
My idea was to loop through the sites, $.post() to calculate.php within every iteration (other things are being done too in the loop, less important) and add to a variable in the callback function. I believe my problem is that $.post() is async... Here is my sample code:
function systems(siteList){
var runningTotal = 0;
for (var ii=0,i<siteList.length,i++){
$.post("calculate.php",{foo:siteList[ii]},function(data){
// important part
runningTotal = runningTotal + data
})
}
//outside loop
alert(runningTotal)
}
This function may be imperfect, but my real question is how can I achieve the result I'm looking for here? Just so you know, runningTotal always alerts as 0 with the above code.
Thanks
EDIT: Thanks to all for your help. from what I can see, it is not wise of me to be using so many AJAX calls so instead of directly fixing this problem, I believe I will take a step back and take the advice of sending only one ajax callback to perform the task of summing for me. Thanks again
Upvotes: 1
Views: 150
Reputation: 816770
I'd suggest to make use of $.when
and run a callback once all Ajax calls are done. At that moment you have access to the response of each Ajax call and you can perform any necessary computation.
For example:
function systems(siteList){
var promises = [];
for (var ii=0; i<siteList.length; i++){
// `$.post` returns a promise. We keep track of each promise.
promises.push($.post("calculate.php",{foo:siteList[ii]}));
}
$.when.apply($, promises).then(function() {
// this is called once the responses of all Ajax calls
// have been received
var sum = 0;
for (var i = 0, l = arguments.length; i < l; i++) {
sum += +arguments[i][0]; // value must be cast to number first
}
alert(sum)
});
}
Have a look at the jQuery documentation to learn more about promises: http://learn.jquery.com/code-organization/deferreds/.
In general though, it's better to make as few Ajax requests as possible. If you can change the server side code, I would change it to accept a list of values, not only one value, and let the server return the final result.
Upvotes: 8
Reputation: 40076
Not very fancy, but you could use a file on the server to store your running total.
As each ajax request is received, read/update total/write
to a file on the server.
Then send that value back either after receiving a specific request (&request=send_total
), or somehow appended to the output for each request ( 50|3753
).
Upvotes: 0
Reputation: 5120
Leaving aside that there should probably be one request doing this sort of summing up the calculations on the server side (IMHO), use a counter and when it reaches 0 you know, you have all results collected:
function systems(siteList){
var runningTotal = 0;
var counter = 0;
for (var ii=0,i<siteList.length,i++){
counter++;
$.post("calculate.php",{foo:siteList[ii]},function(data){
// important part
runningTotal = runningTotal + data
counter--;
if(counter==0)
alert(runningTotal)
});
}
}
Upvotes: 2
Reputation: 3526
I recommend you package up your data on the client side (in JavaScript) and send it to the server in one AJAX request. Multiple requests waste bandwidth and time.
Or, if the calculations are simple and don't need a database or some other external dependency, just move your calculations to a library of javascript functions and do it all client side.
Upvotes: 2
Reputation: 146310
AJAX is asynchronous.
Do the alert inside of the AJAX callback.
Upvotes: -3