2012-01-16 2 views
0

나는 내가 겪고있는 문제가 무엇인지 알고있다. 나는 그저 주위를 둘러 보는데 어려움을 겪고있다. 나는 누군가가 이와 같은 것을 경험했는지 그리고 그들이 구현 한 해결책이 무엇인지 궁금해하고있었습니다.Javascript 스택 오버플로가 실행되는 동안 setTimeout 메서드 + 전달 변수

나는 보류중인 수리 목록 시스템을 가지고 있으며, 나는 검은 색과 빨간색으로 깜박이는 늦은 수리를 원합니다. 이 목록에 여러 개의 수리가 늦었을 가능성이 있습니다. 내가 repsToBlink라고 점멸해야하는 항목에 대한 "ID의"의 배열이

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

:

여기 내 기능입니다.

다음 코드를 실행하여 이러한 각 복구에 대해 설정된 깜박임 간격을 얻습니다.이 깜박임 간격은 재귀 루프에 넣습니다.

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

스택 오버플로가 발생하지 않고이 코드를 어떻게 수행 할 수 있습니까?

감사합니다.

+1

순수한 CSS로 이것을 수행하려면 [this] try (http://jsfiddle.net/Krr7m/)를 시도하십시오. [MDN] (https://developer.mozilla.org/en/CSS/CSS_animations)에서 자세한 정보를 얻을 수 있습니다. 더 많은 브라우저에서 작동하려면 벤더 특정 접두사를 추가해야하며 이전 브라우저에서는 작동하지 않습니다. –

+0

저는 각 요소에 대해'setTimeout()'에 대한 열렬한 팬이 아닙니다. 목록을 대신 사용하십시오 : http://jsfiddle.net/HdCbt/ –

+0

[Maximum Call Stack Size Exceeded] (http://stackoverflow.com/questions/8731840/)의 dup, [왜 괄호가있는 setTimeout은 새로운 callstack?] (http://stackoverflow.com/questions/8058996/). – outis

답변

3

당신은에

setTimeout(setblink(id),500); 

에서의 setTimeout을 변경해야합니다.

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 (...;...;...))의 loop over the integer indices 아닌 속성 (for ... in). 그러나 대신 ids에 값이 아닌 인덱스가있는 객체를 사용하는 경우 for ... in이 적합합니다.

위의 내용은 각각 id에 대한 별도의 타이머를 실행합니다 (브라우저에 부담을 줄 수 있음). 루프를 스케줄링 할 수있는 유일한 기능이되는 기능으로 이동 시키면 단일 타이머 만 필요합니다.

주기적으로 기능을 실행 중이므로 setInterval이 더 적절합니다.

repsToBlink에서 ID를 제거 할 때마다 나머지가 있는지 확인하십시오. 그렇지 않은 경우 간격을 취소하십시오. 당신이 함수의 결과를 전달하는 반면,

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

setTimeout()이 함수는 매개 변수로 전달 될 것으로 기대 :

(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

문제는 글로벌 컨텍스트에서 setTimeout이 호출되고 있다는 것입니다. 바로 그 기능을 즉시 호출합니다. 그것은이 코드에 도달

인터프리터 :

setTimeout(setblink(id),500);

는 함수의 반환 값이 타임 아웃이 호출하도록되어 무엇 가정, 즉시 setblink 함수를 호출한다. 이것은 재귀 함수이므로 스택 오버플로가 발생합니다.

수정하려면 setTimeout이 function(){} 내에서 호출 할 함수를 래핑하십시오.

관련 문제