Returns only last callback in javascript / jQuery?
I am trying to create a simple autocomplete list:
DOM:
<input id="example"/> <div id="results"></div> JavaScript:
$('#example').keyup(function(e) { $('#results').empty(); $.getJSON('Search?input=' + $('#example').val(), function(response) { // This attaches the results to the results div updateAutocomplete(response); }); }); This works, except when the user is typing, I could get the callbacks in a different order. Anyway, around? I thought about tying the timestamp to the results and doing a quick comparison (this way, if an earlier answer is received later, it will be rejected). This should be a common problem, what is the best way to get around this?
You can save and cancel the previous request along the way, for example:
var xhr; $('#example').keyup(function(e) { $('#results').empty(); if(xhr) { xhr.abort(); xhr = null; //cleanup } xhr = $.getJSON('Search?input=' + $('#example').val(), function(response) { updateAutocomplete(response); }); }); $.getJSON() returns the created XmlHttpRequest, so we just attach a link to it and interrupt if necessary.
Delay will be helpful. So let's see what these posts say: Is jquery activation delay?
var delay = (function(){ var timer = 0; return function(callback, ms){ clearTimeout (timer); timer = setTimeout(callback, ms); }; })(); Using:
$('input').keyup(function() { delay(function(){ alert('Time elapsed!'); }, 1000 ); }); ( CMS code)
I usually chose a few things ...
- have a slight delay before sending (200-250 ms) ... (for example, the request queue), if another keystroke arrives, ignore the old requests.
- save the last keyword you are asking for ... in your results, be sure to return the keyword and make sure that the keyword matches the last before displaying.
Just use closure for the callback function with incremental identifier for each callback instance. Something like that:
var id = 0; function next_autocomplete_handler() { var handler_id = ++id; return function(response) { if (handler_id == id) // is this latest latest? updateAutocomplete(response); }; } $('#example').keyup( function(e) { $('#results').empty(); $.getJSON('Search?input=' + $('#example').val(), next_autocomplate_handler()); });