Documentation

AjaxQueue

From jQuery JavaScript Library

Jump to: navigation, search

NOTICE: An Ajax Queue plugin has been created!

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.