I find I sometimes need to iterate some collection and make an ajax call for each element. I want each call to return before moving to the next element so that I don't blast the server with requests - which often leads to other issues. And I don't want to set async to false and freeze the browser.
Usually this involves setting up some kind of iterator context that i step thru upon each success callback. I think there must be a cleaner simpler way?
Does anyone have a clever design pattern for how to neatly work thru a collection making ajax calls for each item?
A quick and small solution using deferred promises. Although this uses jQuery's
$.Deferred
, any other should do.Usage, call to create new queues:
See the example with a side-by-side comparison of asynchronous requests.
I would suggest a bit more sophisticated approach which is reusable for different cases.
I am using it for example when I need to slow down a call sequence when the user is typing in text editor.
But I am sure it should also work when iterating through the collection. In this case it can queue requests and can send a single AJAX call instead of 12.
You can wrap all that complexity into a function to make a simple call that looks like this:
Below is a rough sketch (working example, except the ajax call). This can be modified to use a queue-like structure instead of an array
jQuery 1.5+
I developed an
$.ajaxQueue()
plugin that uses the$.Deferred
,.queue()
, and$.ajax()
to also pass back a promise that is resolved when the request completes.jQuery 1.4
If you're using jQuery 1.4, you can utilize the animation queue on an empty object to create your own "queue" for your ajax requests for the elements.
You can even factor this into your own
$.ajax()
replacement. This plugin$.ajaxQueue()
uses the standard 'fx' queue for jQuery, which will auto-start the first added element if the queue isn't already running.Example Usage
So, we have a
<ul id="items">
which has some<li>
that we want to copy (using ajax!) to the<ul id="output">
jsfiddle demonstration - 1.4 version
Yeah, while the other answers will work, they are lots of code and messy looking. Frame.js was designed to elegantly address this situation. https://github.com/bishopZ/Frame.js
For instance, this will cause most browsers to hang:
While this will not:
Also, using Frame allows you to waterfall the response objects and deal with them all after the entire series of AJAX request have completed (if you want to):
I use http://developer.yahoo.com/yui/3/io/#queue to get that functionality.
The only solutions I can come up with is, as you say, maintaining a list of pending calls / callbacks. Or nesting the next call in the previous callback, but that feels a bit messy.