I am using JQuery to do an ajax calls to fetch data. I am doing several calls to fetch peices of this data incrementally. So I have something like:
for(i=0;i<numOfDataObjects;i++) {
$.ajax({
//get开发者_运维百科 the data and do something with it in the success callback
});
}
I have some code after this loop that I want executed only after all the ajax calls have completed and the success callbacks exited. Right now this is not happening, I guess because of the asynchronous nature of the xhr object.
Is there a way, without incrementing a global counter in each ajax success function (and checking if it equals a certain value), to ensure that the code after the loop gets executed after all the server calls have completed?
You can use the jQuery Message Queueing plugin. Put all the items you need to process, into a queue. Notice the complete
function in the documentation:
complete: (Function) Called whenever there are no longer any queue items to process. After completion, if more queue items are added and the queue completes again, this function will be called again. Inside this function,
this
refers to the queueObj object.
Put the code that you want to run inside that handler.
One caveat though. I can't tell from the documentation if the complete
handler is called after the callbacks have been executed for each AJAX request, or if it is immediately called when there are no items left to process in the queue (regardless of whether there are currently-executing AJAX requests).
UPDATE
I seem to have ignored the callback
function:
callback: (Function) Called for each queue item or batch of items, every delay milliseconds. This function is passed a single argument, which is the single queue item if batch is 1, or an array of queue items if batch is > 1. If callback returns true, the queue item(s) will be re- added back onto the front of the queue for the next callback execution to retry. Inside this function,
this
refers to the queueObj object.
I imagine that you can put everything you need to send into a batch and put the code that you need to run inside the callback
handler.
There is an extension to the JavaScript language called StratifiedJS. It runs in every browser, and it allows you to handle asynchronous calls like that in a linear way.
You can enable Stratified JavaScript e.g. by including Oni Apollo ( http://onilabs.com/docs ) in your webpage like:
<script src="http://code.onilabs.com/latest/oni-apollo.js"></script>
<script type="text/sjs"> your StratifiedJS code here </script>
And your code would look something like:
var http = require("http"); // a module wrapping XHR, part of Apollo
for(i=0;i<numOfDataObjects;i++) {
//get the data
var data = http.get(url);
// and do something with it
}
But that would execute all requests sequentially, you can also execute all requests in parallel (so the browser can make multiple connections at once) and continue on the next line when they're all done:
function handleParallelRequests(urls) {
if (!urls.length) return;
waitfor {
var data = require('http').get(urls[0]);
// and do something with it
}
and {
// in parallel, do remaining requests:
// continue with the urls without the first we just handled.
handleParallelRequests(urls.slice(1));
}
}
handleParallelRequest(myurls);
// all request are finished when you get here.
the waitfor/and keyword is explained at http://stratifiedjs.org/sjsdocs
精彩评论