http://jquery.com/plugins/project/ajaxqueue
This page documents some concepts and ideas for an AJAX queue plugin.
To start with, here are a few mails pasted from the discussion list:
I recently ran into a situation similar to the one shown in this screencast: http://www.phppatterns.com/stuff/latency.html
The short version: Rapidly dispatched Asynchronous Javascript requests don't always return to the client in the same order they were sent, introducing odd behavior.
In my experience, 99.9% of the time, this is not an issue. However, that 0.1% is killing me.
I wanted to start some discussion about whether this might be addressed within jQuery, how to address it, should it be a plugin, etc. I'd be happy to write one.
Additional Links on the topic: http://www.sitepoint.com/blogs/2006/11/16/race-conditions-ajax-and-sessions/ http://www.sitepoint.com/blogs/2006/02/10/ajaxlocalhost/ http://ajaxblog.com/archives/2005/06/01/async-requests-over-an-unreliable-network
Here's another great example with a solution.
http://www.cmarshall.net/MySoftware/ajax/index.html
His code is large and in charge, but looks like he's done a good job. I'm positive we could optimize this with jQuery.
You may also want to cancel Ajax requests (as is the case with autocomplete), but I don't know if you can do that with jQuery. Maybe something like:
$.ajax({
type: "GET",
url: "autocomplete.php",
queue: "autocomplete",
cancelExisting: true
})
Which would cancel an existing request in the 'autocomplete' queue if a new request is made and the old request hasn't finished.
Maybe also a function to stop all current requests? $.stopAjax(function(){alert("All Ajax requests stopped")}) or those in a queue $.stopAjax("autocomplete", function(){alert("autocomplete Ajax requests stopped")})
I've been bothered about this also. The simplest approach is to do what TCP/IP does - number each response, and ignore all but the latest response.
To elaborate: since you can have multiple, parallel, independent streams of Ajax going on, you need to number those also - call them ports. For each port, you take only the response with the highest number.
Eg: Response (processed) port=1; response=2;
Response (ignored) port=1; response=1;
Response (processed) port=2; response=1;
Last, once we're handling this, we may as well kill all old requests once a newer response has come in - this cuts down on server load.
A basic draft for a ajaxQueue plugin API:
// setup general queue behaviour
$.remoteQueue.setup({
// the url to use for all following queue request
url: "/",
type: "post",
// additional data to add to each request
data: { ... },
// wait for 50ms before sending a request, if another request starts before this one, drop the first
delay: 50,
// specify setup only for a single port (see $.queue.request)
port: 5
// whether to cancel ongoing request when a new one is added
cancel: true
});
// start a request, used instead of $.ajax; if cancel is set, clears all previous requests, useful for autocomplete
$.remoteQueue.request({
// the actual data to send with this request
data: { ... },
// a virtual port to use for the request, necessary when using more then one queue, can be a number of string
port: 5
});
// clear requests, dropping both not-started and aborting those already started, useful for autocomplete when user blurs field
$.remoteQueue.clear({
// specify port to clear only the queue, otherwise clear all
port: 5
})
An implementation should be heavily tested with automated tests, jQuery's testsuite should help a lot. An example from jQuery's ajax tests:
test("$.ajax - simple post", function() {
expect(1);
stop();
$.ajax({
type: "POST",
url: url("data/name.php"),
data: "name=peter",
success: function(msg){
ok( msg == 'pan', 'Check for POST' );
start();
}
});
});
Just include testrunner.js on the testpage.