javascript 等待函数完成的 setInterval 的替代方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11063242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Alternative to setInterval that waits for function to complete
提问by Morgan
Currently, I'm using setInterval to run several AJAX functions that call PHP pages like so -
目前,我正在使用 setInterval 来运行几个 AJAX 函数,这些函数像这样调用 PHP 页面 -
var intervalOne = setInterval(ajaxfunction, 1500);
This works fine on a test server with a tiny response time. However occasionally on my live server, there will be a bit of lag and the interval time will come again before the first one has finished, repeating the same call, and causing duplicate data to appear.
这在响应时间很短的测试服务器上运行良好。但是偶尔在我的实时服务器上,会有一点延迟,并且间隔时间会在第一个完成之前再次出现,重复相同的调用,并导致出现重复的数据。
Is there any way to keep the same interval time, but have it wait to call the function if the first one hasn't finished yet?
有没有办法保持相同的间隔时间,但是如果第一个还没有完成,让它等待调用该函数?
Alternatively, Is there anything I can put in a readystate portion of the AJAX calls to have them trigger themselves again once they are complete?
或者,我可以在 AJAX 调用的就绪状态部分放入任何内容,以便在调用完成后再次触发它们吗?
Edit - Example of one of my ajax calls:
编辑 - 我的 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);
}
回答by Amadan
The easy way is through blindly reapplying setTimeout
at the end of your process:
最简单的方法是setTimeout
在流程结束时盲目地重新申请:
function foo() {
// possibly long task
setTimeout(foo, 1500);
}
foo();
This would wait 1500ms between your processes. Like this: 300ms process, 1500ms wait, 2000ms process, 1500ms wait, 400ms process, 1500ms wait...
这将在您的进程之间等待 1500 毫秒。像这样:300ms进程,1500ms等待,2000ms进程,1500ms等待,400ms进程,1500ms等待......
A bit more closely to what you want, you could reapply setTimeout
at the beginningof your process. In this case, you'd get: 300ms process, 1200ms wait, 2000ms process, 0ms wait, 400ms process, 1100ms wait... The problem that happens with setInterval
doesn't happen here, because this only schedules the nextiteration, not all future ones. Notice also that since JS is single-threaded, an event can't interrupt itself like you could get in some other languages.
更接近您想要的,您可以setTimeout
在流程开始时重新申请。在这种情况下,你会得到:300ms 进程,1200ms 等待,2000ms 进程,0ms 等待,400ms 进程,1100ms 等待......发生的问题setInterval
不会在这里发生,因为这只会安排下一次迭代,而不是全部未来的。还要注意,由于 JS 是单线程的,事件不能像其他语言一样中断自己。
function foo() {
setTimeout(foo, 1500);
// possibly long task
}
foo();
And yeah, I guess it's more popular these days to make it self-executing, as you can see in some answers; but that's just aesthetics, the end effect is the same.
是的,我想现在更流行让它自动执行,正如你在一些答案中看到的那样;但这只是美学,最终效果是一样的。
回答by Tomasz Nurkiewicz
You can replace setInterval()
with setTimeout()
being constantly rescheduled on every AJAX response:
您可以替换setInterval()
与setTimeout()
每个Ajax响应不断被重新安排:
function Send() {
//...
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4) {
setTimeout(Send, 1500);
//...
}
}
}
Send();
If you don't need millisecond precision this is fine (time between calls will be 1500 ms + average response time). If you need to call the server exactly every 1500 milliseconds you can subtract response time from 1500 ms.
如果您不需要毫秒精度,这很好(调用之间的时间将为 1500 毫秒 + 平均响应时间)。如果您需要精确地每 1500 毫秒调用一次服务器,您可以从 1500 毫秒中减去响应时间。
回答by Sarfraz
You can create a self invoking function along with setTimeout
like this:
您可以创建一个自调用函数,setTimeout
如下所示:
(function foo(){
// your code logic here
setTimeout(foo, 5000);
})();
The difference here is that it would work similar to setInterval
but unlike it, the next call to function will be run only after your code logic here
part has finished executing.
这里的区别在于它的工作方式setInterval
与它相似但不同的是,下一次调用函数只会在your code logic here
部分执行完毕后运行。
See the DEMOhere.
请参阅此处的演示。