替代setInterval等待函数完成

时间:2012-06-16 12:03:03

标签: javascript ajax

目前,我正在使用setInterval来运行几个调用PHP页面的AJAX函数 -

var intervalOne = setInterval(ajaxfunction, 1500);

这在响应时间很短的测试服务器上运行良好。然而,偶尔在我的实时服务器上,会有一些延迟,并且间隔时间将在第一个完成之前再次出现,重复相同的调用,并导致重复数据出现。

有没有办法保持相同的间隔时间,但如果第一个还没有完成,还等待调用该函数吗?

或者,有什么东西可以放在AJAX调用的状态部分中,让它们在完成后再次触发它们吗?

编辑 - 我的一个ajax调用示例:

function Send() {
var name = document.getElementById('name').value;
var message = document.getElementById('message').value;

var xmlhttp = getXMLHttp();

xmlhttp.onreadystatechange = function() {
    if(xmlhttp.readyState == 4)
    {
        document.getElementById('message').value = "";

        if(xmlhttp.responseText != "") {
            var chat = document.getElementById('messagebox');
            chat.innerHTML = chat.innerHTML + '<div class=\"alert\">' + xmlhttp.responseText + '</div>';
            chat.scrollTop = 1000000000;
        }
    }
}

xmlhttp.open("POST","submit_message.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("name=" + name + "&message=" + message);

}

3 个答案:

答案 0 :(得分:6)

简单的方法是在流程结束时盲目地重新应用setTimeout

function foo() {
  // possibly long task
  setTimeout(foo, 1500);
}
foo();

这将在您的进程之间等待1500毫秒。像这样:300ms进程,1500ms等待,2000ms进程,1500ms等待,400ms进程,1500ms等待...

更接近您想要的内容,您可以在流程的开头重新应用setTimeout。在这种情况下,你会得到:300毫秒进程,1200毫秒等待,2000毫秒进程,0毫秒等待,400毫秒进程,1100毫秒等待... setInterval发生的问题在这里不会发生,因为这只会调度 next 迭代,而不是所有未来的迭代。另请注意,由于JS是单线程的,因此事件不能像其他语言一样中断自身。

function foo() {
  setTimeout(foo, 1500);
  // possibly long task
}
foo();

是的,我猜这些日子让它自我执行更受欢迎,正如你在一些答案中看到的那样;但这只是美学,最终效果是一样的。

答案 1 :(得分:3)

您可以将setInterval()替换为setTimeout(),并在每次AJAX响应时不断重新安排:

function Send() {
    //...
    xmlhttp.onreadystatechange = function() {
        if(xmlhttp.readyState == 4) {
            setTimeout(Send, 1500);
            //...
        }
    }
}

Send();

如果你不需要毫秒精度,这很好(通话之间的时间是1500毫秒+平均响应时间)。如果您需要每1500毫秒调用一次服务器,则可以从1500毫秒减去响应时间。

答案 2 :(得分:2)

你可以像setTimeout一样创建一个自我调用函数:

(function foo(){

 // your code logic here

 setTimeout(foo, 5000);

})();

这里的不同之处在于它的工作方式类似于setInterval,但与之不同,下一次调用函数只能在your code logic here部分执行完毕后运行。

请在此处查看 DEMO