我从多个地方读到,当设置一些基本永久运行的东西时,setTimeout()比setInterval()更可取。下面的代码运行良好,但运行了大约一个小时后(38.0.1)抛出了too much recursion错误。
本质上,我让它从counts.php抓取少量文本,并使用该信息更新表。根据检验员的说法,整个通话和回程大约需要50毫秒。我正试着让它按照t的指示每x秒做一次。
我怀疑如果切换到setInterval(),这可能会有效,但我不确定setTimeout()与setInterval()思维的当前状态是什么,因为我发现的所有东西都在3-5岁左右。
$(document).ready(function() {
t = 3000;
$.ajaxSetup({cache: false});
function countsTimer(t) {
setTimeout(function () {
$.getJSON("counts.php", function (r) {
$(".count").each(function(i,v) {
if ($(this).html() != r[i]) {
$(this).fadeOut(function () {
$(this)
.css("color", ($(this).html() < r[i]) ? "green" : "red")
.html(r[i])
.fadeIn()
.animate({color: '#585858'}, 10000);
})
};
});
t = $(".selected").html().slice(0,-1) * ($(".selected").html().slice(-1) == "s" ? 1000 : 60000);
countsTimer(t);
});
}, t);
};
countsTimer(t);
});更新:通过在.fadeOut()动画之前添加.stop(真,真)解决了这个问题。此问题仅在Firefox中发生,因为在其他浏览器中进行测试不会引起任何问题。我认为答案是正确的,尽管它不是这个特殊情况下的解决办法,而是提供了一个更一般意义上的很好的解释。
发布于 2015-05-25 19:17:27
在这种情况下,您确实应该切换到setInterval()。setInterval()的问题是,如果要清除超时,则必须保留引用,如果操作(可能)比超时本身执行的时间更长,则操作可能会运行两次。
例如,如果一个函数使用setInterval每1s运行一次,但是由于XHR请求较慢,该函数本身需要2s才能完成,该函数在某个时候将同时运行两次。这往往是不可取的。通过使用setTimout并调用原始函数的末尾,函数永不重叠,所设置的超时始终是两个函数调用之间的时间。
但是,在您的情况下,您的应用程序运行时间似乎很长,因为您的函数每3秒运行一次,函数调用堆栈将每3秒增加一个。除非您中断这个递归循环,否则这是无法避免的。例如,只有在收到浏览器事件(如单击文档和检查时间)时,才能执行请求。
(function()
{
var lastCheck = Date.now(), alreadyRunning = false;
document.addEventListener
(
"click",
function()
{
if(!alreadyRunning && Date.now() - lastCheck > 3000)
{
alreadyRunning = true;
/* Do your request here! */
//Code below should run after your request has finished
lastCheck = Date.now();
alreadyRunning = false;
}
}
)
}());这没有setInterval的缺点,因为您总是检查代码是否已经运行,但是只有在接收到浏览器事件时才会运行检查。(这通常不是问题。)这种方法会产生更多的样板。
因此,如果您确信XHR请求的完成时间不会超过3s,只需使用setInterval()即可。
编辑:上面的答案在某些方面是错误的,
正如注释中指出的那样,setTimeout()确实没有增加调用堆栈的大小,因为它在调用超时中的函数之前返回。此外,问题中的函数不包含任何特定的递归。我将保留这个答案,因为问题的一部分是关于setTimeout()和setInterval()。但是,导致递归错误的问题可能出现在其他代码中,因为在示例代码中的任何地方都没有函数直接或间接地调用自己。
https://stackoverflow.com/questions/30444224
复制相似问题