使用 setTimeout 定期进行自动完成 AJAX 调用?

Posted

技术标签:

【中文标题】使用 setTimeout 定期进行自动完成 AJAX 调用?【英文标题】:Use setTimeout to periodically make autocomplete AJAX calls? 【发布时间】:2011-09-16 17:55:57 【问题描述】:

我想使用一个 setTimeout 函数,这样 Ajax 调用最多只能每 1 秒进行一次。

这就是我所拥有的。这显然是不正确的,但我不确定 setTimeout 函数是如何工作的。

function autoComplete(q, succ)


    setTimeout(

    if(q != "") 
        $.ajax(type:"GET",
            url: "php/search.php",
            data: "q="+q,
            success: succ
        );
    

    , 1000);

我认为我应该使用 clearTimeout 以便如果再次调用,它将重置计时器并再等待 1 秒,但是当我尝试实现它时它停止运行该函数。

【问题讨论】:

我什至不确定您要达到的目标。退后一步,想想你要解决的问题。你开始一个 ajax 调用:它继续。你在第一个完成之前立即开始另一个:它应该发生什么?它是否应该因“不到一秒”的错误而失败?它应该排队等待一秒钟后执行吗?如果我在一秒钟之前将其中的 1000 个排队怎么办:你想要一个包含 1000 个等待 ajax 调用的队列吗?从某种意义上说,它们不会“衰减”:不再需要它们请求的数据吗?不知何故,我认为 setTimeout 不是问题。 【参考方案1】:

传递一个...函数:)

使用匿名函数可能如下:

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);
    

注意,我将q 的支票移到外面。这不会同时运行两次超时,但可能有多个进行中的请求。为了防止这种情况,success 回调需要一个守卫——一个简单的方法是使用一个计数器。用setTimeout 中的q 检查“当前q”可能会导致微妙的竞争条件。

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);
    

更智能的版本可能会在提交时读取 current 值,因为上面的代码总是会滞后一秒...

现在,假设getQ 是一个函数对象...

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)

编码愉快。


需要考虑的一点是,上面没有提到,可能仍然有多个进行中的请求(第二个示例中的守卫只显示了如何“丢弃”旧响应,不是如何适当地限制请求)。这可以通过短队列和阻止提交新的 AJAX 请求来处理,直到获得回复或足够的“超时”到期并且请求被视为无效。

【讨论】:

谢谢。你的回答超出了我的要求。这对我有很大帮助。 为什么这个答案没有得到更高的评价? ......更高!【参考方案2】:

你也可以试试这个方法

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

【讨论】:

以上是关于使用 setTimeout 定期进行自动完成 AJAX 调用?的主要内容,如果未能解决你的问题,请参考以下文章

SQL2005自动备份,定期删除的维护计划及自动定期清除日志

DBA使用Shell完成自动化相关工作

SQL Server 2008如何创建定期自动备份任务

自动或定期备份 mysql 数据

使用 PayPal REST API 进行定期付款

定期HTTP GET请求,而不使用“提交”输入