setblink(id)
calls the function immediately. A stack overflow is a symptom of immediate, rather than delayed, execution since setTimeout
schedules execution for later so the future invocation won't get pushed on the current call stack.
Since setblink
takes an argument, wrap it in a nullary anonymous function for 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]);
}
The code calls for more improvements.
If repsToBlink
is an array, you should loop over the integer indices of repsToBlink
(for (...;...;...)
), not the properties (for ... in
). However, if instead you were to use an object with the ids an indices (rather than values), for ... in
would be appropriate.
The above fires a separate timer for each id
(which could overwhelm the browser). By moving the loop to a function, which becomes the only function to be scheduled, only a single timer is required.
Since you're running a function periodically, setInterval
is more appropriate.
Whenever you remove and id from repsToBlink
, check whether there are any remaining; if not, cancel the interval.
(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;
})();