I'm looking at the jQuery UI autocomplete documentation and looking at their example of a callback with caching:
$(function() {
var cache = {}, lastXhr;
$('#Field').autocomplete({
minLength: 2,
delay: 600,
source: function(request, response) {
var term = request.term;
if( term in cache ) {
response(cache[term]);
return;
}
lastXhr = $.post('LoadData', function(data, status, xhr) {
cache[term] = data;
if(xhr === lastXhr) {
response(data);
}
});
}
});
});
The code wires up a field to use autocomplete and stores a cache of queries that have been hit already. The following line is used so if one query takes longer than another it doesn't replace the autocomplete values:
if(xhr === lastXhr) {
response(data);
}
If I start typing a few letters and it goes to the server to query the data, then I pause and start typing again, it will trigger another trip to the server. If the first query finishes AFTER the second one then the loading icon never goes away. I assume this is because it is never calling the response()
callback. Is there a way that I can cancel the first request once a second request is made?
Could you just add lastXhr.abort()
right before you do the post? This would cancel a previous request each time you start a new one.
$(function() {
var cache = {}, lastXhr;
$('#Field').autocomplete({
minLength: 2,
delay: 600,
source: function(request, response) {
var term = request.term;
if( term in cache ) {
response(cache[term]);
return;
}
// Abort previous access if one is defined
if (typeof lastXhr !== 'undefined' && lastXhr.hasOwnProperty("abort")) {
lastXhr.abort();
}
lastXhr = $.post('LoadData', function(data, status, xhr) {
cache[term] = data;
if(xhr === lastXhr) {
response(data);
// Set to undefined, we are done:
// helps when deciding to abort
lastXhr = undefined;
}
});
}
});
});
response(null)
because then it will clear the list. Need to be able to somehow tell autocomplete that the call has finished without overriding the data - Dismissile 2012-04-04 20:21
Cache your final result along with the request. You can then make sure that the response callback is called every time and the lastData will ensure that the correct data is used, regardless of whether the queries come back out of sync.
As in:
$(function() {
var cache = {}, lastXhr,lastData;
$('#Field').autocomplete({
minLength: 2,
delay: 600,
source: function(request, response) {
var term = request.term;
if( term in cache ) {
response(cache[term]);
return;
}
lastXhr = $.post('LoadData', function(data, status, xhr) {
cache[term] = data;
if(xhr === lastXhr) {
response(data);
// Store the latest data
lastData = data;
}
else
{
// Queries have come back out of sync - this isn't the last one
// but we need to call response to stop the spinner
response(lastData);
}
});
}
});
});