10

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

var intervalOne = setInterval(ajaxfunction, 1500);

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

有什么方法可以保持相同的间隔时间,但是如果第一个还没有完成,它是否要等待调用该函数?

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

编辑 - 我的一个 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);

}
4

3 回答 3

12

setTimeout简单的方法是在流程结束时盲目地重新申请:

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

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

更接近您想要的,您可以setTimeout在流程开始时重新申请。在这种情况下,你会得到:300ms 进程,1200ms 等待,2000ms 进程,0ms 等待,400ms 进程,1100ms 等待......发生的问题setInterval不会在这里发生,因为这只会安排一次迭代,而不是全部未来的。还要注意,由于 JS 是单线程的,事件不能像其他语言那样中断自己。

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

是的,我想现在更流行的是让它自动执行,正如你在一些答案中看到的那样;但这只是美学,最终效果是一样的。

于 2012-06-16T12:07:00.953 回答
4

您可以替换setInterval()setTimeout()在每个 AJAX 响应上不断重新安排:

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

Send();

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

于 2012-06-16T12:07:34.013 回答
3

您可以像这样创建一个自调用函数setTimeout

(function foo(){

 // your code logic here

 setTimeout(foo, 5000);

})();

这里的区别在于它的工作方式setInterval与它相似但不同,下一次调用函数将仅在your code logic here部分完成执行后运行。

在此处查看演示

于 2012-06-16T12:06:34.033 回答