Autocomplete - remote data, race condition

Autocomplete - remote data, race condition

I've started working with the jQuery UI 1.8 Autcomplete recently with remote data.   I was pleased with the ease of initial implementation, but before long I ran into a classic race condition.

As I type, the search query gets more specific, so it takes less time for the server respond.  As a consequence, it is possible for the old response to arrive after the most recent one.  Obviously, this is producing undesirable effects.

I'm a little frustrated that the plugin doesn't have a way to manage this.  To me, it seems that it makes the "basic" remote data implementation unreliable in most real-world situations.  It also seems as though this would be a common problem, but I've found very little literature on it.

I've found that autocomplete is a relatively new addtion to jQuery UI, so I've put the frustration aside and started my own widget which extends autocomplete to solve for three things: 1) race conditions; 2) animated open/close; 3) caching.

The nature of this post is two-fold.  Not only to share information I've gathered on the topic of race conditions with others who might be having the same trouble, but to (hopefully) gain some insight to how other people are solving for this.

The first piece of this puzzle was that $.ajax() (and related methods) return an XMLHTTPRequest instance.  As described at stackoverflow.com, this grants us the ability to use XMLHTTPRequest.abort() method.  So I just keep a handle to the XMLHTTPRequest instance, and if it exists, call abort() before the next request is made.

Using a firebug, I could see that the requests were being aborted as expected and the symptoms of the race-condition ceased.  So far, so good... then I got to IE.  Not so much.

In IE, I was seeing run-time errors.  The odd thing is that the run-time errors seemed to be coming from deep within jQuery UI, rather than my code yet commenting out the abort() avoided the run-times.  After scratching my head for a while, I used the following simplified code to shed some light on the situation:

  1. function goTest()
  2.   {
  3.     var xhr = $.ajax({
  4.       url: 'test.php',
  5.       dataType:'json',
  6.       data: {term:'b'},
  7.       success: function (data, textStatus)
  8.       {
  9.         alert(data + '|' + textStatus);
  10.       }
  11.     });

  12.     xhr.abort();

  13.   }
  14.   $(document).ready(goTest);

In Firefox and Chrome, behavior is as expected - no alert box.  However, in IE6 and IE8 (IE7 untested at this time), the success handler still fires!  As it turns out, the run-time errors were because the response was undefined as it got passed through my success code path.  My next thought was, "maybe I can just evaluate textStatus".  Unfortunately, it turns out (as seen in the alert box) it contains the string "success".

My next course of action will be to evaluate the contents of data before passing it through to the next method, and I believe that will fix the problem.  However, I am very interested in hearing thoughts from others on this.  

Is there a better way to handle this sort of thing?