jquery setTimeout 太多递归
jquery setTimeout too much recursion
我从多个地方了解到,在将某些内容设置为永远 运行 时,setTimeout() 比 setInterval() 更可取。下面的代码工作正常,但在 运行ning Firefox (38.0.1) 大约一个小时后抛出 too much recursion
.
错误
基本上,我让它从 counts.php 中抓取了非常少量的文本,并用该信息更新了 table。根据检查员的说法,整个调用和 return 大约需要 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(true, true) 解决了这个问题。此问题仅发生在 Firefox 中,因为在其他浏览器中进行测试未导致任何问题。我已将答案标记为正确,尽管它不是这种特定情况下的解决方案,而是从更一般的意义上提供了一个很好的解释。
在这种情况下,您确实应该切换到 setInterval()。 setInterval() 的问题是,如果您想要清除超时,您要么必须保留一个引用,并且如果操作(可能)执行的时间比超时本身长,则操作可能是 运行 两次。
例如,如果您有一个函数 运行 每 1 秒使用 setInterval,但是由于 XHR 请求较慢,该函数本身需要 2 秒才能完成,该函数将同时 运行 两次时间在某个时候。这通常是不希望的。通过使用 setTimout 并在原始函数的末尾调用它,函数永远不会重叠,您设置的超时始终是两个函数调用之间的时间。
但是,在您的情况下,您的应用程序似乎很长-运行,因为您的函数每 3 秒运行一次,函数调用堆栈将每 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() 确实不会增加调用堆栈大小,因为它 returns 在调用超时函数之前。此外,问题中的函数不包含任何特定的递归。我会保留这个答案,因为部分问题是关于 setTimeout() 与 setInterval() 的。但是,导致递归错误的问题可能出在其他一些代码中,因为示例代码中的任何地方都没有直接或间接调用自身的函数。
我从多个地方了解到,在将某些内容设置为永远 运行 时,setTimeout() 比 setInterval() 更可取。下面的代码工作正常,但在 运行ning Firefox (38.0.1) 大约一个小时后抛出 too much recursion
.
基本上,我让它从 counts.php 中抓取了非常少量的文本,并用该信息更新了 table。根据检查员的说法,整个调用和 return 大约需要 50 毫秒。我试图让它按照 t
.
我怀疑如果我切换到 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() 的问题是,如果您想要清除超时,您要么必须保留一个引用,并且如果操作(可能)执行的时间比超时本身长,则操作可能是 运行 两次。
例如,如果您有一个函数 运行 每 1 秒使用 setInterval,但是由于 XHR 请求较慢,该函数本身需要 2 秒才能完成,该函数将同时 运行 两次时间在某个时候。这通常是不希望的。通过使用 setTimout 并在原始函数的末尾调用它,函数永远不会重叠,您设置的超时始终是两个函数调用之间的时间。
但是,在您的情况下,您的应用程序似乎很长-运行,因为您的函数每 3 秒运行一次,函数调用堆栈将每 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() 确实不会增加调用堆栈大小,因为它 returns 在调用超时函数之前。此外,问题中的函数不包含任何特定的递归。我会保留这个答案,因为部分问题是关于 setTimeout() 与 setInterval() 的。但是,导致递归错误的问题可能出在其他一些代码中,因为示例代码中的任何地方都没有直接或间接调用自身的函数。