I'm using the callback version of the source
option which performs an ajax request. I figure if a user types a bunch of letters in rapid succession before an ajax request completes, we should abort the old one and only use the new one. I'm assuming the URL version for the source
parameter would do this automatically, but since I'm using a custom callback, I'd have to do that manually.
So here's what I've got:
$('#myselector').autocomplete({
source: function(request, response) {
var data = {};
if($(this).data('xhr')) {
console.log('aborting...');
$(this).data('xhr').abort();
}
// *snip* add some stuff to data
$(this).data('xhr', $.ajax({
url: '/ajax/major_city',
dataType: 'json',
data: data,
success: function(data, textStatus, $xhr) {
response(data);
},
complete: function($xhr, textStatus) {
console.log(textStatus);
if(textStatus === 'abort') {
console.log('aborted!');
response([]);
}
}
}));
},
// ....
So, whenever the "source" callback is triggered, it checks if the XHR element exists for that input (will be undefined the first time), and if so, aborts it (side question: how can I check if the request is complete? No sense trying abort requests that have already completed).
But the docs say:
It's important when providing a custom source callback to handle errors during the request. You must always call the response callback even if you encounter an error. This ensures that the widget always has the correct state.
So, towards the bottom of my code you'll see that I (attempt to) check if the request has been aborted, and if so, I return an empty list. But that "aborted!" log never seems to be called. It always says "success" even when it gets aborted. Why's that?
Edit: Just tried outputting $(this).data('xhr').readyState
. It never seems to be less than 4
which suggests to me that source
isn't called again until the last request returns a response. Which is a shame, because we could abort the requests early and speed up the response time a bit...
Increase the time the plugin waits before sending the request:
$( ".selector" ).autocomplete({ delay: 500 }); //default is 300
This way you will only send the request once you suspect the user has finished typing. It's better to make less http requests than make many and cancel them.
-Lededje
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With