运行setTimeout方法+传递变量的Javascript堆栈溢出
我知道我遇到的问题是,我只是很难找到解决办法。我想知道是否有人经历过这样的事情,他们实施了什么样的解决方案。运行setTimeout方法+传递变量的Javascript堆栈溢出
我有一个名单系统,等待维修,我想这是迟到闪烁黑色和红色修理。这个列表中有很多修复可能很晚。
这里是我的功能:
function setblink(id) {
var elm = document.getElementById(id);
if (elm.color == "red"){
elm.color = "black";
}
else{
elm.color = "red";
}
setTimeout(setblink(id),500);
}
我有“的ID”对于需要闪烁称为repsToBlink项目的数组。
我得到通过运行下面的代码,这使他们在递归循环运行的每个这些修复的设定眨眼的时间间隔。
for(var x in repsToBlink){
setTimeout(setblink(repsToBlink[x]),500);
}
我怎样才能得到这段代码做同样的事情,而不会导致堆栈溢出?
谢谢!
您需要在setTimeout的从
setTimeout(setblink(id),500);
更改为:
setTimeout(function() { setblink(id) },500);
setTimeout()
预期的功能,如参数传递,而你传递函数的结果。
setblink(id)
立即调用该函数。由于setTimeout
计划稍后执行,因此堆栈溢出是立即执行而非延迟执行的症状,因此未来的调用不会被推送到当前调用堆栈上。
由于setblink
需要一个参数,因此将其包装在一个nullary匿名函数中,用于lazy evaluation。
function setblink(id) {
var elm = document.getElementById(id);
if (elm.color == "red"){
elm.color = "black";
}
else{
elm.color = "red";
}
setTimeout(function() {setblink(id)},500);
}
for (var x in repsToBlink){
(function (id) {
setTimeout(function() {setblink(id)},500);
})(repsToBlink[x]);
}
该代码要求进一步改进。
如果repsToBlink
是一个数组,你应该的repsToBlink
(for (...;...;...)
)loop over the integer indices,而不是性能(for ... in
)。但是,如果您要使用带有ID索引(而不是值)的对象,则适合使用for ... in
。
上述火灾每个id
(其可能压倒浏览器)一个单独的定时器。通过将循环移到一个函数中,该函数成为唯一需要调度的函数,只需要一个计时器。
既然你正在运行一个函数定期,setInterval
是比较合适的。
每当你从repsToBlink
删除和ID,检查是否有任何剩余;如果没有,则取消间隔。
(function() {
var repsToBlink, repCount=0, blinkInterval;
function startBlinking(ids) {
addRepsToBlink(ids);
if (! blinkInterval) {
blinkInterval = setTimeout(blinkAll, 500);
}
}
function addRepsToBlink(ids) {
for (var i=0; i<ids.length; ++i) {
addRep(ids[i]);
}
}
function addRep(id) {
if (! id in repsToBlink) {
++repCount;
repsToBlink[ids[i]] = true;
}
}
function removeRep(id) {
if (id in repsToBlink) {
delete repsToBlink[id];
--repCount;
if (!repCount) {
clearInterval(blinkInterval);
blinkInterval=0;
}
}
}
function blinkAll() {
for (id in repsToBlink) {
blink(id);
}
}
function blink(id) {
var elm = document.getElementById(id);
if (elm.color == "red"){
elm.color = "black";
} else {
elm.color = "red";
}
}
window.startBlinking = startBlinking;
window.addRepsToBlink = addRepsToBlink;
window.addRep = addRep;
window.removeRep = removeRep;
})();
您的问题是setTimeout
正在全局上下文中调用。那,你马上就会调用这个函数。
的解释,当它到达此代码:
setTimeout(setblink(id),500);
立即调用setblink
功能,假设该函数的返回值是什么超时应该调用。这会导致堆栈溢出,因为这是一个递归函数。
为了解决这个问题,将setTimeout函数调用到function(){}
之内。
如果你想用纯CSS做这个试试[this](http://jsfiddle.net/Krr7m/)。有关[MDN]的更多信息(https://developer.mozilla.org/en/CSS/CSS_animations)。您需要添加更多供应商特定的前缀才能使其适用于更多浏览器,并且不适用于旧版浏览器。 – 2012-01-16 18:21:26
我不是每个元素的'setTimeout()'的忠实粉丝。使用列表,而不是:http://jsfiddle.net/HdCbt/ – 2012-01-16 18:48:32
[超过最大调用堆栈大小]的Dup(http://*.com/questions/8731840/),[为什么使用括号调用setTimeout不启动新的callstack?](http://*.com/questions/8058996/)。 – outis 2012-01-16 19:19:24