Javascript堆栈溢出,同时运行setTimeout方法+传递变量

时间:2012-01-16 18:12:00

标签: javascript html dynamic timeout settimeout

我知道我遇到的问题是,我只是很难找到一个解决方法。我想知道是否有人经历过这样的事情,以及他们实施了什么样的解决方案。

我有一个待处理维修的清单系统,我想要修复黑色和红色的眨眼。此列表中可能存在多次修复,但这些修复都很晚。

这是我的功能:

function setblink(id) {
   var elm = document.getElementById(id);
    if (elm.color == "red"){
        elm.color = "black";
    }
    else{
        elm.color = "red";
    }
    setTimeout(setblink(id),500);
}

我有一个“id's”数组,用于需要闪烁的项目,称为repsToBlink。

通过运行以下代码,我为每个修复运行设置的闪烁间隔,这使它们处于递归循环中。

for(var x in repsToBlink){
setTimeout(setblink(repsToBlink[x]),500);
}

如何在不导致堆栈溢出的情况下让此代码执行相同的操作?

谢谢!

3 个答案:

答案 0 :(得分:3)

您需要从

更改setTimeout
setTimeout(setblink(id),500);

为:

setTimeout(function() { setblink(id) },500);

setTimeout()期望函数作为参数传递,而您传递函数的结果。

答案 1 :(得分:2)

setblink(id)立即调用该函数。堆栈溢出是立即执行而不是延迟执行的症状,因为setTimeout计划执行以便稍后执行,因此将来的调用不会被推送到当前调用堆栈。

由于setblink接受了一个参数,请将其包装在nullarylazy 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 (...;...;...)for ... in),而不是属性(loop over the integer indices)。但是,如果您使用带有ids的对象(而不是值),id将是合适的。

上面为每个setInterval触发了一个单独的计时器(这可能会使浏览器不堪重负)。通过将循环移动到一个函数,该函数成为唯一要调度的函数,只需要一个计时器。

由于您定期运行某个功能,repsToBlink更合适。

每当您从(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; })(); 移除并识别时,请检查是否有剩余的内容;如果没有,取消间隔。

{{1}}

答案 2 :(得分:1)

您的问题是在全局范围内调用setTimeout。那,你立即调用这个函数。

解释器,当它到达此代码时:

setTimeout(setblink(id),500);

正在立即调用setblink函数,假设该函数的返回值是超时应该调用的值。这会导致堆栈溢出,因为这是一个递归函数。

要修复此问题,请将setTimeout的函数包装在function(){}内调用。