I need to make a series of N ajax requests without locking the browser, and want to use the jquery deferred object to accomplish this.
Here is a simplified example with three requests, but my program may need to queue up over 100 (note that this is not the exact use case, the actual code does need to ensure the success of step (N-1) before executing the next step):
$(document).ready(function(){ var deferred = $.Deferred(); var countries = ["US", "CA", "MX"]; $.each(countries, function(index, country){ deferred.pipe(getData(country)); }); }); function getData(country){ var data = { "country": country }; console.log("Making request for [" + country + "]"); return $.ajax({ type: "POST", url: "ajax.jsp", data: data, dataType: "JSON", success: function(){ console.log("Successful request for [" + country + "]"); } }); }
Here is what gets written into the console (all requests are made in parallel and the response time is directly proportional to the size of the data for each country as expected:
Making request for [US] Making request for [CA] Making request for [MX] Successful request for [MX] Successful request for [CA] Successful request for [US]
How can I get the deferred object to queue these up for me? I've tried changing done to pipe but get the same result.
Here is the desired result:
Making request for [US] Successful request for [US] Making request for [CA] Successful request for [CA] Making request for [MX] Successful request for [MX]
Edit:
I appreciate the suggestion to use an array to store request parameters, but the jquery deferred object has the ability to queue requests and I really want to learn how to use this feature to its full potential.
This is effectively what I'm trying to do:
when(request[0]).pipe(request[1]).pipe(request[2])... pipe(request[N]);
However, I want to assign the requests into the pipe one step at a time in order to effectively use the each traversal:
deferred.pipe(request[0]); deferred.pipe(request[1]); deferred.pipe(request[2]);
The jQuery library provides a way to make any callback function waiting for multiple Ajax calls. This method is based on an object called Deferred. A Deferred object can register callback functions based on whether the Deferrred object is resolved or rejected. Here is an example of the Deferred object.
To iterate through the response, there is a callback function attached to it. This callback function gets executed once both the Ajax requests are finished. In case where multiple Deferred objects are passed to $. when() , it takes the response returned by both calls, and constructs a new promise object.
There is a requirement to make multiple AJAX calls parallelly to fetch the required data and each successive call depends on the data fetched in its prior call. Since AJAX is asynchronous, one cannot control the order of the calls to be executed.
The function B () is then called with the results of the Ajax call as its first argument. When the ajax call in B () completes, it resolves the promise and function C () is called with the results of that call and so on. Here we are just adding return in every function to make this chain work.
Definition and Usage The ajax () method is used to perform an AJAX (asynchronous HTTP) request. All jQuery AJAX methods use the ajax () method. This method is mostly used for requests where the other methods cannot be used.
This API provides the response in JSON format. To make your API call, first create your Free Account in their website and get your API KEY. Then use this KEY to make API calls with jQuery AJAX. In my application there is a HTML Select control and a button.
With jQuery, you can chain together actions/methods. Chaining allows us to run multiple jQuery methods (on the same element) within a single statement. Until now we have been writing jQuery statements one at a time (one after the other).
With a custom object
function DeferredAjax(opts) { this.options=opts; this.deferred=$.Deferred(); this.country=opts.country; } DeferredAjax.prototype.invoke=function() { var self=this, data={country:self.country}; console.log("Making request for [" + self.country + "]"); return $.ajax({ type: "GET", url: "wait.php", data: data, dataType: "JSON", success: function(){ console.log("Successful request for [" + self.country + "]"); self.deferred.resolve(); } }); }; DeferredAjax.prototype.promise=function() { return this.deferred.promise(); }; var countries = ["US", "CA", "MX"], startingpoint = $.Deferred(); startingpoint.resolve(); $.each(countries, function(ix, country) { var da = new DeferredAjax({ country: country }); $.when(startingpoint ).then(function() { da.invoke(); }); startingpoint= da; });
Fiddle http://jsfiddle.net/7kuX9/1/
To be a bit more clear, the last lines could be written
c1=new DeferredAjax( {country:"US"} ); c2=new DeferredAjax( {country:"CA"} ); c3=new DeferredAjax( {country:"MX"} ); $.when( c1 ).then( function() {c2.invoke();} ); $.when( c2 ).then( function() {c3.invoke();} );
With pipes
function fireRequest(country) { return $.ajax({ type: "GET", url: "wait.php", data: {country:country}, dataType: "JSON", success: function(){ console.log("Successful request for [" + country + "]"); } }); } var countries=["US","CA","MX"], startingpoint=$.Deferred(); startingpoint.resolve(); $.each(countries,function(ix,country) { startingpoint=startingpoint.pipe( function() { console.log("Making request for [" + country + "]"); return fireRequest(country); }); });
http://jsfiddle.net/k8aUj/1/
Edit : A fiddle outputting the log in the result window http://jsfiddle.net/k8aUj/3/
Each pipe call returns a new promise, which is in turn used for the next pipe. Note that I only provided the sccess function, a similar function should be provided for failures.
In each solution, the Ajax calls are delayed until needed by wrapping them in a function and a new promise is created for each item in the list to build the chain.
I believe the custom object provides an easier way to manipulate the chain, but the pipes could better suit your tastes.
Note : as of jQuery 1.8, deferred.pipe()
is deprecated, deferred.then
replaces it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With