Use setTimeout to periodically make autocomplete AJAX calls?
I would like to use a setTimeout function so that Ajax calls are only made at the most every 1 second.
Here is what I have. This is clearly not correct, but I am not sure how the setTimeout function works.
function autoComplete(q, succ)
{
setTimeout(
i开发者_开发技巧f(q != "") {
$.ajax({type:"GET",
url: "php/search.php",
data: "q="+q,
success: succ
});
}
, 1000);
}
I think that I should use clearTimeout so that if another call is made, it will reset the timer and wait another 1 second, but when I tried to implement this it stopped running the function.
Pass a ... function :)
Using an anonymous function might be as follows:
var timeoutId
function autoComplete(q, succ)
{
if (q) {
// stop previous timeouts
clearTimeout(timeoutId)
timeoutId = setTimeout(function () {
$.ajax({type:"GET",
url: "php/search.php",
data: "q="+q,
success: succ
});
}, 1000);
}
}
Note I move the check for q
outside. This won't run two timeouts at once, but there may be multiple in-flight requests. To guard against this, the success
callback needs a guard -- and a simple way to do this is with a counter. Checking the "current q" with the q
in the setTimeout
may lead to subtle race conditions.
var timeoutId
var counter = 0
function autoComplete(q, succ)
{
if (q) {
// Increment counter to maintain separate versions
counter++
var thisCounter = counter
clearTimeout(timeoutId)
timeoutId = setTimeout(function () {
$.ajax({type:"GET",
url: "php/search.php",
data: "q="+q,
success: function () {
// Only call success if this is the "latest"
if (counter == thisCounter) {
succ.apply(this, arguments)
}
},
});
}, 1000);
}
}
A smarter version might read the current value at time of submission because the above code will always lag one second behind...
Now, imagine getQ
is a function object...
var timeoutId
var counter = 0
function autoComplete(getQ, succ)
{
counter++
var thisCounter = counter
clearTimeout(timeoutId)
timeoutId = setTimeout(function () {
var q = getQ() // get the q ... NOW
if (q) {
$.ajax({type:"GET",
url: "php/search.php",
data: "q="+q,
success: function () {
if (counter == thisCounter) {
succ.apply(this, arguments)
}
},
});
}
}, 1000);
}
// example usage
autoComplete(function () { return $(elm).val() }, successCallback)
Happy coding.
One thing to consider, not addressed in the above, is that there may still be multiple in-flight requests (the guard in the 2nd example only shows how to "throw out" old responses, not how to limit requests appropriately). This can be handled with a short-queue and prevention of submitting a new AJAX request until either the reply is obtained or a sufficient "timeout" has expired and the request is considered invalid.
You can try this way also,
var textInput = document.getElementById('input');
var timeout = null; // default set
textInput.onkeyup = function (e) {
// If it has already been set cleared first.
clearTimeout(timeout);
// set timeout to 500ms
timeout = setTimeout(function () {
console.log('Input Value:', textInput.value);
}, 500);
};
<input type="text" id="input">
精彩评论