Apart from making synchronous AJAX calls if you can and think it is appropriate, what is the best way to handle something like this?
var A = getDataFromServerWithAJAXCall(whatever);
var B = getDataFromServerWithAJAXCallThatDependsOnPreviousData(A);
var C = getMoreDataFromServerWithAJAXCall(whatever2);
processAllDataAndShowResult(A,B,C);
Provided开发者_运维问答 that I can pass callbacks to those functions, I know I can use closures and lambdas to get the job done like this:
var A,B,C;
getDataFromServerWithAJAXCall(whatever, function(AJAXResult) {
A= AJAXResult;
getDataFromServerWithAJAXCallThatDependsOnPreviousData(A, function(AJAXResult2) {
B= AJAXResult2;
processAllDataAndShowResult(A,B,C);
});
});
getMoreDataFromServerWithAJAXCall(whatever2, function(AJAXResult) {
C= AJAXResult;
processAllDataAndShowResult(A,B,C);
});
function processAllDataAndShowResult(A,B,C) {
if(A && B && C) {
//Do stuff
}
}
But it doesn't feel right or clean enough to me. So is there a better way or at least a cleaner way to do the same thing or is it just that I'm not used to javascript functional programming?
By the way, I'm using jQuery (1.4.2) if that helps.
Thank you.
Yes, jQuery's Deferred Object is super handy.
Here's the example from the $.when()
function documentation, illustrating a solution to your problem:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
/* a1 and a2 are arguments resolved for the
page1 and page2 ajax requests, respectively */
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
if ( /Whip It/.test(jqXHR.responseText) ) {
alert("First page has 'Whip It' somewhere.");
}
});
Cheers!
Make the callback function of each AJAX call to check/store results in a common local storage. And have another processing function that reads from this container, maybe at regular intervals or activated by each callback. This way you keep you functions clean and the focus on the Ajax call. This also keeps the accumulation scalable to n Ajax calls easy, and you dont have to modify existing code when adding a new call.
If you can use jQuery 1.5 you should be able to accomplish your needs via using the deferred object and $.when()
$.when(getDataFromServerWithAJAXCall("Call 1"), getMoreDataFromServerWithAJAXCall("Call 2")).done(function(a1, a2) {
var jqXHR = a1[2];
jqXHR.responseText;
getDataFromServerWithAJAXCallThatDependsOnPreviousData(jqXHR.responseText);
});
Simply put when the first two functions complete then it will execute the third function.
Example on jsfiddle
Use a so-called 'countdown latch'
- Each of the functions have their own callback.
- Have a variable called
countdownlatch
be upped each time a function is called and count-down when each of the callbacks is reached (be sure to countdown on async error as well. - Each of the callbacks separately checks to see if
countdownlatch==0
if so call functionprocessAllDataAndShowResult
The beauty of javascript with these kind of async synchronizations is that implementing a countdownlatch is super-easy, because javascript is single-threaded, i.e: there's no way countdownlatch
could get funky numbers because of racing conditions since these are non-existent (in this situation).
EDIT
Didn't see B depended on A, but the same principle applies:
var A,B,C;
var cdlatch = 2;
getDataFromServerWithAJAXCall(whatever, function(AJAXResult) {
A= AJAXResult;
getDataFromServerWithAJAXCallThatDependsOnPreviousData(A, function(AJAXResult2) {
B= AJAXResult2;
if(--cdlatch === 0){
processAllDataAndShowResult(A,B,C);
}
});
});
getMoreDataFromServerWithAJAXCall(whatever2, function(AJAXResult) {
C= AJAXResult;
if(--cdlatch === 0){
processAllDataAndShowResult(A,B,C);
}
});
function processAllDataAndShowResult(A,B,C) {
//Do stuff
}
I must admit it's not that clear as the general case I described earlier, oh well.
精彩评论