我知道我遇到的问题是,我只是很难找到一个解决方法。我想知道是否有人经历过这样的事情,以及他们实施了什么样的解决方案。
我有一个待处理维修的清单系统,我想要修复黑色和红色的眨眼。此列表中可能存在多次修复,但这些修复都很晚。
这是我的功能:
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);
}
如何在不导致堆栈溢出的情况下让此代码执行相同的操作?
谢谢!
答案 0 :(得分:3)
您需要从
更改setTimeoutsetTimeout(setblink(id),500);
为:
setTimeout(function() { setblink(id) },500);
setTimeout()
期望函数作为参数传递,而您传递函数的结果。
答案 1 :(得分:2)
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 (...;...;...)
(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(){}
内调用。