我从多个地方了解到,当设置某些东西基本上永远运行时,setTimeout() 比 setInterval() 更可取。下面的代码工作正常,但在运行 Firefox (38.0.1) 大约一个小时后,会抛出太多递归
错误。
本质上,我让它从 counts.php 中获取非常少量的文本,并使用该信息更新表格。据检查人员称,整个调用和返回大约需要50ms。我试图让它按照 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(true, true) 得到解决。此问题仅出现在 Firefox 中,在其他浏览器中测试并未出现任何问题。我已将答案标记为正确,尽管它不是这种特殊情况下的解决方案,但它在更一般的意义上提供了一个很好的解释。
最佳答案
在这种情况下,您确实应该切换到 setInterval()。 setInterval() 的问题是,如果您想清除超时,则必须保留引用,并且万一操作(可能)执行时间比超时本身更长,则操作可能会运行两次。
例如,如果您有一个使用 setInterval 每 1 秒运行一次的函数,但由于 XHR 请求缓慢,该函数本身需要 2 秒才能完成,则该函数在某个时刻将同时运行两次。这通常是不希望的。通过使用 setTimout 并在原始函数末尾调用该函数,函数永远不会重叠,并且您设置的超时始终是两个函数调用之间的时间。
但是,在您的情况下,您似乎有一个长时间运行的应用程序,因为您的函数每 3 秒运行一次,所以函数调用堆栈将每三秒增加 1。除非打破这个递归循环,否则这是无法避免的。例如,您只能在收到浏览器事件(例如单击文档并检查时间)时执行请求。
(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 请求完成时间不会超过 3 秒,只需使用 setInterval()。
编辑:上面的答案在某些方面是错误的
正如评论中指出的,setTimeout() 确实不会增加调用堆栈大小,因为它在调用超时内的函数之前返回。此外,问题中的函数不包含任何特定的递归。我会保留这个答案,因为问题的一部分是关于 setTimeout() 与 setInterval() 的。但是,导致递归错误的问题可能出现在其他代码段中,因为示例代码中的任何位置都没有直接或间接调用自身的函数。
关于javascript - jquery setTimeout 太多递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30444224/