program tip

Javascript, setTimeout 루프?

radiobox 2020. 10. 18. 09:15
반응형

Javascript, setTimeout 루프?


그래서 저는 여러 자바 스크립트 요소가 다른 요소와 동기화되어야하는 음악 프로그램을 작업하고 있습니다. 처음에는 정말 잘 작동하는 setInterval을 사용해 왔지만 시간이 지남에 따라 요소가 점차적으로 동기화되지 않아 음악 프로그램과 나쁘게됩니다.

나는 setTimeout이 더 정확하다는 것을 온라인으로 읽었으며 어떻게 든 setTimeout 루프를 가질 수 있지만 이것이 어떻게 가능한지 보여주는 일반 버전을 찾지 못했습니다. 누군가가 setTimeout을 사용하여 무기한으로 반복하는 기본 예제를 보여줄 수 있습니까?

감사합니다. 또는 setInterval 또는 다른 함수를 사용하여 더 많은 동기 결과를 얻을 수있는 방법이 있으면 알려주십시오.

편집하다:

기본적으로 다음과 같은 기능이 있습니다.

//drums
setInterval(function {
//code for the drums playing goes here
},8000);

//chords
setInterval(function {
//code for the chords playing goes here
},1000);

//bass
setInterval(function {
//code for the bass playing goes here
},500);

처음에는 매우 잘 작동하지만 약 1 분 동안 setInterval에서 읽었을 때 소리가 눈에 띄게 동기화되지 않습니다. setTimeout이 더 일관되게 정확할 수 있다는 것을 읽었습니다.


setTimeout재귀를 사용하여 루프를 만들 수 있습니다 .

function timeout() {
    setTimeout(function () {
        // Do Something Here
        // Then recall the parent function to
        // create a recursive loop.
        timeout();
    }, 1000);
}

와 문제 setInterval()setTimeout()코드가 지정된 시간에 실행된다는 보장이 없다는 것이다. setTimeout()이를 재귀 적으로 사용 하고 호출하면 다음 코드 반복이 시작되기 전에 시간 제한 내의 모든 이전 작업이 완료되도록 할 수 있습니다.


보충하기 위해서만. 변수를 전달하고 반복해야하는 경우 다음과 같이 할 수 있습니다.

function start(counter){
  if(counter < 10){
    setTimeout(function(){
      counter++;
      console.log(counter);
      start(counter);
    }, 1000);
  }
}
start(0);

산출:

1
2
3
...
9
10

초당 한 줄.


어느 시간도 매우 정확하지 않을 setTimeout것이므로 조금 더 정확하게 사용 하는 한 가지 방법 은 마지막 반복 이후 지연 시간을 계산 한 다음 적절하게 다음 반복을 조정하는 것입니다. 예를 들면 :

var myDelay = 1000;
var thisDelay = 1000;
var start = Date.now();

function startTimer() {    
    setTimeout(function() {
        // your code here...
        // calculate the actual number of ms since last time
        var actual = Date.now() - start;
        // subtract any extra ms from the delay for the next cycle
        thisDelay = myDelay - (actual - myDelay);
        start = Date.now();
        // start the timer again
        startTimer();
    }, thisDelay);
}

따라서 처음으로 1000ms를 기다릴 때 코드가 실행될 때 약간 늦을 수 있습니다 (예 : 1046ms). 따라서 다음주기에 대한 지연에서 46ms를 빼면 다음 지연이 954ms에 불과합니다. 이것은 타이머가 늦게 실행되는 것을 막지는 못하지만 (예상되는) 지연을 막는 데 도움이됩니다. (참고 : thisDelay < 0어떤 지연이 목표 지연의 두 배 이상이고주기를 놓쳤는 지 확인하고 싶을 수 있습니다.

물론 이것은 여러 타이머를 동기화 상태로 유지하는 데 도움이되지 않을 것입니다.이 경우 동일한 타이머로 모든 타이머를 제어하는 ​​방법을 알아 내고 싶을 수 있습니다.

따라서 코드를 보면 모든 지연이 500의 배수이므로 다음과 같이 할 수 있습니다.

var myDelay = 500;
var thisDelay = 500;
var start = Date.now();
var beatCount = 0;

function startTimer() {    
    setTimeout(function() {
        beatCount++;
        // your code here...
        //code for the bass playing goes here  

        if (count%2 === 0) {
            //code for the chords playing goes here (every 1000 ms)
        }

        if (count%16) {
            //code for the drums playing goes here (every 8000 ms)
        }

        // calculate the actual number of ms since last time
        var actual = Date.now() - start;
        // subtract any extra ms from the delay for the next cycle
        thisDelay = myDelay - (actual - myDelay);
        start = Date.now();
        // start the timer again
        startTimer();
    }, thisDelay);
}

오디오 타이밍을 처리하는 가장 좋은 방법은 Web Audio Api를 사용하는 것입니다. 메인 스레드에서 발생하는 상황에 관계없이 정확한 별도의 클럭이 있습니다. 여기에 Chris Wilson의 훌륭한 설명, 예제 등이 있습니다.

http://www.html5rocks.com/en/tutorials/audio/scheduling/

더 많은 웹 오디오 API를 위해이 사이트를 둘러보십시오. 그것은 당신이 원하는 것을 정확하게 수행하도록 개발되었습니다.


저는 직장 생활에서 이렇게 사용합니다.이 경우에는 "공통 루프를 잊어 버림"을 사용하고 "setInterval"조합을 사용하면 "setTimeOut"이 포함됩니다.

    function iAsk(lvl){
        var i=0;
        var intr =setInterval(function(){ // start the loop 
            i++; // increment it
            if(i>lvl){ // check if the end round reached.
                clearInterval(intr);
                return;
            }
            setTimeout(function(){
                $(".imag").prop("src",pPng); // do first bla bla bla after 50 millisecond
            },50);
            setTimeout(function(){
                 // do another bla bla bla after 100 millisecond.
                seq[i-1]=(Math.ceil(Math.random()*4)).toString();
                $("#hh").after('<br>'+i + ' : rand= '+(Math.ceil(Math.random()*4)).toString()+' > '+seq[i-1]);
                $("#d"+seq[i-1]).prop("src",pGif);
                var d =document.getElementById('aud');
                d.play();                   
            },100);
            setTimeout(function(){
                // keep adding bla bla bla till you done :)
                $("#d"+seq[i-1]).prop("src",pPng);
            },900);
        },1000); // loop waiting time must be >= 900 (biggest timeOut for inside actions)
    }

PS: Understand that the real behavior of (setTimeOut): they all will start in same time "the three bla bla bla will start counting down in the same moment" so make a different timeout to arrange the execution.

PS 2: the example for timing loop, but for a reaction loops you can use events, promise async await ..


setTimeout loop problem with solution

// it will print 5 times 5.
for(var i=0;i<5;i++){
setTimeout(()=> 
console.log(i), 
2000)
}               // 5 5 5 5 5

// improved using let
for(let i=0;i<5;i++){
setTimeout(()=> 
console.log('improved using let: '+i), 
2000)
}

// improved using closure
for(var i=0;i<5;i++){
((x)=>{
setTimeout(()=> 
console.log('improved using closure: '+x), 
2000)
})(i);
} 


Use setInterval()

setInterval(function(){
 alert("Hello"); 
}, 3000);

The above will execute alert("Hello"); every 3 seconds.



function appendTaskOnStack(task, ms, loop) {
    window.nextTaskAfter = (window.nextTaskAfter || 0) + ms;

    if (!loop) {
        setTimeout(function() {
            appendTaskOnStack(task, ms, true);
        }, window.nextTaskAfter);
    } 
    else {
        if (task) 
            task.apply(Array(arguments).slice(3,));
        window.nextTaskAfter = 0;
    }
}

for (var n=0; n < 10; n++) {
    appendTaskOnStack(function(){
        console.log(n)
    }, 100);
}


Use let instead of var in code :

for(let i=1;i<=5;i++){setTimeout(()=>{console.log(i)},1000);}

I think it's better to timeout at the end of the function.

function main(){
    var something; 
    make=function(walkNr){
         if(walkNr===0){
           // var something for this step      
           // do something
         }
         else if(walkNr===1){
           // var something for that step 
           // do something different
         }

         // ***
         // finally
         else if(walkNr===10){
           return something;
         }
         // show progress if you like
         setTimeout(funkion(){make(walkNr)},15,walkNr++);  
   }
return make(0);
}   

This three functions are necessary because vars in the second function will be overwritten with default value each time. When the program pointer reach the setTimeout one step is already calculated. Then just the screen needs a little time.

참고URL : https://stackoverflow.com/questions/22154129/javascript-settimeout-loops

반응형