views:

53

answers:

6

I've build a livesearch with the jQuery.ajax() method. On every keyup events it receives new result data from the server.

The problem is, when I'm typing very fast, e.g. "foobar" and the GET request of "fooba" requires more time than the "foobar" request, the results of "fooba" are shown.

To handle this with the timeout parameter is impossible, I think.

Has anyone an idea how to solve this?

A: 

Assign a unique, incrementing ID to each request, and only show them in incrementing order. Something like this:

var counter = 0, lastCounter = 0;
function doAjax() {
  ++counter;
  jQuery.ajax(url, function (result) {
    if (counter < lastCounter)
      return;
    lastCounter = counter;
    processResult(result);
  });
}
Wim
A: 

You should only start the search when the user hasn't typed anything for a while (500ms or so). This would prevent the problem you're having.

An excellent jQuery plugin which does just that is delayedObserver:

http://code.google.com/p/jquery-utils/wiki/DelayedObserver

Philippe Leybaert
Good comment. It doesn't guarantee to solve his problem though if the difference in response times can be greater than .5s (which is easily the case with highly-loaded shared hosting).
Wim
A: 

Make it so each cancels the last. That might be too much cancellation, but when typing slows, it will trigger.

Eli
A: 

That seems like an intense amount of traffic to send an ajax request for every KeyUp event. You should wait for the user to stop typing - presumably that they are done, for at least a few 100 milliseconds.

What I would do is this:

var ajaxTimeout;

function doAjax() {
     //Your actual ajax request code
}


function keyUpHandler() {
    if (ajaxTimeout !== undefined) 
        clearTimeout(ajaxTimeout);

    ajaxTimeout = setTimeout(doAjax, 200);
}

You may have to play with the actual timeout time, but this way works very well and does not require any other plugins.

Edit: If you need to pass in parameters, create an inline function (closure).

...
var fun = function() { doAjax(params...) };
ajaxTimeout = setTimeout(fun, 200);
partkyle
A: 

You will want some kind of an ajax queue such as:

http://plugins.jquery.com/project/ajaxqueue

or http://www.protofunc.com/scripts/jquery/ajaxManager/

EDIT:Another option, study the Autocomplete plug-in code and emulate that.(there are several Autocomplete as well as the one in jquery UI OR just implement the Autocomplete if that serves your needs

Mark Schultheiss
+1  A: 

You can store and .abort() the last request when starting a new one, like this:

var curSearch;
$("#myInput").keyup(function() {
  if(curSearch) curSearch.abort(); //cancel previous search
  curSearch = $.ajax({ ...ajax options... }); //start a new one, save a reference
});

The $.ajax() method returns the XmlHttpRequest object, so just hang onto it, and when you start the next search, abort the previous one.

Nick Craver