AjaxQueue and jQuery 1.3
The website that I work on for the majority of my time had been running on the rather out of date jQuery 1.2 for quite some time. I recently found myself with a little bit of downtime and decided it was a good time to see if we could upgrade and take advantage of all the speed improvements that the latest version gives us.
On the most part, the upgrade was fairly painless. Most things worked without change but one particular plug-in did not – AjaxQueue. This is a great little control that acts as an add-on to the ajax method of jQuery, allowing a little more control over how concurrent calls are processed. It gives three modes of operation but for us, the most useful of these are abort and queue and from the names it is fairly obvious what they do.
After I upgraded to jQuery 1.3, it did not take me long to realise that the queue mode was broken. I briefly looked around for an alternative plug-in but found that all of them would require too much change to our existing controls. There was no alternative, I had to open up the hood of AjaxQueue and see what had gone wrong.
What I found was that there must of been a change to a method that the plug-in relied on – a method that it seemed, only became publicly available in version 1.3 – queue. Although the function was similar, the conclusion that I came to was that prior to version 1.3, the queue function automatically de-queued any function added and processed it. When using the latest jQuery, the ajax calls were queued but there was no code to start the processing of the queue.
It was slightly more complex I thought it would be to get it going – I had to ensure the queue was only started once. I finally came up with a solution and a newly revived plug-in, the code of which is below. As the original plugin has not been touched for quite some time (2007), I thought it ok to post my modified version here.
(function($) { var ajax = $.ajax, pendingRequests = {}, synced = [], syncedData = [], ajaxRunning = []; $.ajax = function(settings) { // create settings for compatibility with ajaxSetup settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings)); var port = settings.port; switch (settings.mode) { case "abort": if (pendingRequests[port]) { pendingRequests[port].abort(); } return pendingRequests[port] = ajax.apply(this, arguments); case "queue": var _old = settings.complete; settings.complete = function() { if (_old) { _old.apply(this, arguments); } if (jQuery([ajax]).queue("ajax" + port).length > 0) { jQuery([ajax]).dequeue("ajax" + port); } else { ajaxRunning[port] = false; } }; jQuery([ajax]).queue("ajax" + port, function() { ajax(settings); }); if (jQuery([ajax]).queue("ajax" + port).length == 1 && !ajaxRunning[port]) { ajaxRunning[port] = true; jQuery([ajax]).dequeue("ajax" + port); } return; case "sync": var pos = synced.length; synced[pos] = { error: settings.error, success: settings.success, complete: settings.complete, done: false }; syncedData[pos] = { error: [], success: [], complete: [] }; settings.error = function() { syncedData[pos].error = arguments; }; settings.success = function() { syncedData[pos].success = arguments; }; settings.complete = function() { syncedData[pos].complete = arguments; synced[pos].done = true; if (pos == 0 || !synced[pos - 1]) for (var i = pos; i < synced.length && synced[i].done; i++) { if (synced[i].error) synced[i].error.apply(jQuery, syncedData[i].error); if (synced[i].success) synced[i].success.apply(jQuery, syncedData[i].success); if (synced[i].complete) synced[i].complete.apply(jQuery, syncedData[i].complete); synced[i] = null; syncedData[i] = null; } }; } return ajax.apply(this, arguments); }; })(jQuery);
14 Responses to “AjaxQueue and jQuery 1.3”
Leave a Reply

arnon on January 11th, 2010
Thank! just what I needed. I got as far as understanding that the queue was not starting to be processed and you came just in time for me.
A well done job it is.
Michael on February 1st, 2010
So, do I understand correctly that this would add a new option ‘mode’ to standard .ajax() calls, to which I should pass either ‘abort’, ‘queue’ or ‘sync’?
dan on February 1st, 2010
@Michael Yes, adding the additional ‘mode’ option is what the original ajaxqueue plugin did. It also added the ‘port’ setting, so you can distinguish between different ajax calls.
jkorbes on March 10th, 2010
Exactly what I was looking for! Thanks very much for posting.
Chris on May 7th, 2010
Thank you! I was having the usual AJAX race condition related problems, and all I had to do was simply drop this in, and it fixed it (the autocomplete plugin we use, the “Bassistance” one, already takes advantage of AJAX queue).
Bruce on May 19th, 2010
So, do I understand correctly that this would add a new option ‘mode’ to standard .ajax() calls, to which I should pass either ‘abort’, ‘queue’ or ‘sync’?
dan on May 19th, 2010
Yes, thats exactly what it does. It also adds a ‘port’ option, which allows you to group requests together.
mat. on June 23rd, 2010
Hi Dan,
Nice work!
I use your solution on my local website, I use jQuery 1.4.2. There is a problem on your solution, the queue length can increase but never decrease, so it’s work for all ajax request which are sent before the first request is completed otherwise it’s blocked. It’s due to the fact that you use the queue length to permut the “ajaxRunning[port]” variable. But the queue length doesn’t reflact the number of request which are not yet sent but reflact the number of ajax request call.
Anyway to solve it?
mat. on June 23rd, 2010
Forget it, it’s work like a charm. My mistake.
dan on June 23rd, 2010
@mat. Happy to have sorted that for you
agentphoenix on June 28th, 2010
I’ve been looking high and low through all kinds of Ajax queuing stuff and this looks promising, but I have a page I’m working on that can have up to 8 Ajax requests, but the user determines how many requests there are. Is there a way with something like this to know when the queue has finished running?
You rock! on July 12th, 2010
i had my crappy solution… but your code rocks! thx!
chris on August 12th, 2010
There is a bug when using the “context” option from the original jQuery.ajax . In the callbacks the false “this” reference is set.
chris on August 12th, 2010
edit:
at least for the “queue” mode it can be fixed if you change all calls of “ajax.apply(this, arguments)” to ajax.apply(settings.context, arguments)
The “sync” mode seems to be more work…