开发者

Use setTimeout to periodically make autocomplete AJAX calls?

开发者 https://www.devze.com 2023-03-13 08:30 出处:网络
I would like to use a setTimeout function so that Ajax calls are only made at the most every 1 second.

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">

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号