[javascript] JavaScript 루프에서 지연을 어떻게 추가합니까?

while루프 안에 지연 / 수면을 추가하고 싶습니다 .

나는 이것을 이렇게 시도했다 :

alert('hi');

for(var start = 1; start < 10; start++) {
  setTimeout(function () {
    alert('hello');
  }, 3000);
}

첫 번째 시나리오 만 해당됩니다.를 표시 한 후 alert('hi')3 초 동안 기다렸다가 alert('hello')표시되지만 alert('hello')반복적으로 계속 표시됩니다 .

내가 원하는 것은 after alert('hello')가 3 초 후에 표시 alert('hi')되고 두 번째 시간 동안 3 초 동안 기다려야한다는 것 alert('hello')입니다.



답변

setTimeout()함수는 차단되지 않으며 즉시 반환됩니다. 따라서 루프는 매우 빠르게 반복되며 3 초 타임 아웃 트리거가 차례로 연속적으로 시작됩니다. 그렇기 때문에 첫 번째 알림이 3 초 후에 표시되고 나머지는 모두 지연없이 계속됩니다.

대신 다음과 같은 것을 사용하고 싶을 수도 있습니다.

var i = 1;                  //  set your counter to 1

function myLoop() {         //  create a loop function
  setTimeout(function() {   //  call a 3s setTimeout when the loop is called
    console.log('hello');   //  your code here
    i++;                    //  increment the counter
    if (i < 10) {           //  if the counter < 10, call the loop function
      myLoop();             //  ..  again which will trigger another 
    }                       //  ..  setTimeout()
  }, 3000)
}

myLoop();                   //  start the loop

자체 호출 함수를 사용하여 반복 횟수를 인수로 전달하여 정리할 수도 있습니다.

(function myLoop(i) {
  setTimeout(function() {
    console.log('hello'); //  your code here                
    if (--i) myLoop(i);   //  decrement i and call myLoop again if i > 0
  }, 3000)
})(10);                   //  pass the number of iterations as an argument


답변

다음과 같이 해보십시오 :

var i = 0, howManyTimes = 10;
function f() {
    alert( "hi" );
    i++;
    if( i < howManyTimes ){
        setTimeout( f, 3000 );
    }
}
f();


답변

ES6를 사용 let하는 경우 다음 을 수행 하는 데 사용할 수 있습니다 .

for (let i=1; i<10; i++) {
    setTimeout( function timer(){
        alert("hello world");
    }, i*3000 );
}

루프가 아닌 각 반복 에 대해 let선언 i하는 것은 무엇입니까? 이런 식으로 전달되는 것은 우리가 원하는 것입니다.setTimeout


답변

ES7부터 루프 를 기다리는 더 좋은 방법이 있습니다 .

// Returns a Promise that resolves after "ms" Milliseconds
function timer(ms) {
 return new Promise(res => setTimeout(res, ms));
}

async function load () { // We need to wrap the loop into an async function for this to work
  for (var i = 0; i < 3; i++) {
    console.log(i);
    await timer(3000); // then the created Promise can be awaited
  }
}

load();

엔진이 await부품에 도달하면 시간 초과를 설정하고 의 실행을 중지합니다async function . 그런 다음 시간 초과가 완료되면 해당 시점에서 실행이 계속됩니다. (1) 중첩 루프, (2) 조건부, (3) 중첩 함수를 지연시킬 수 있으므로 매우 유용합니다.

async function task(i) { // 3
  await timer(1000);
  console.log(`Task ${i} done!`);
}

async function main() {
  for(let i = 0; i < 100; i+= 10) {
    for(let j = 0; j < 10; j++) { // 1
      if(j % 2) { // 2
        await task(i + j);
      }
    }
  }
}

main();

function timer(ms) { return new Promise(res => setTimeout(res, ms)); }

MDN에 대한 참조

ES7은 이제 NodeJS 및 최신 브라우저에서 지원되지만 BabelJS 로 변환 하여 어디서나 실행될 수 있습니다.


답변

또 다른 방법은 시간 초과 시간을 곱하는 것이지만 이것은 수면과는 다릅니다 . 루프 후 코드는 즉시 실행되며 콜백 함수 실행 만 지연됩니다.

for (var start = 1; start < 10; start++)
    setTimeout(function () { alert('hello');  }, 3000 * start);

첫 번째 제한이 설정 될 것이다 3000 * 1두 번째로, 3000 * 2등등.


답변

이 작동합니다

for (var i = 0; i < 10; i++) {
  (function(i) {
    setTimeout(function() { console.log(i); }, 100 * i);
  })(i);
}

이 바이올린을 사용해보십시오 : https://jsfiddle.net/wgdx8zqq/


답변

나는 당신이 이와 같은 것을 필요로한다고 생각합니다 :

var TimedQueue = function(defaultDelay){
    this.queue = [];
    this.index = 0;
    this.defaultDelay = defaultDelay || 3000;
};

TimedQueue.prototype = {
    add: function(fn, delay){
        this.queue.push({
            fn: fn,
            delay: delay
        });
    },
    run: function(index){
        (index || index === 0) && (this.index = index);
        this.next();
    },
    next: function(){
        var self = this
        , i = this.index++
        , at = this.queue[i]
        , next = this.queue[this.index]
        if(!at) return;
        at.fn();
        next && setTimeout(function(){
            self.next();
        }, next.delay||this.defaultDelay);
    },
    reset: function(){
        this.index = 0;
    }
}

테스트 코드 :

var now = +new Date();

var x = new TimedQueue(2000);

x.add(function(){
    console.log('hey');
    console.log(+new Date() - now);
});
x.add(function(){
    console.log('ho');
    console.log(+new Date() - now);
}, 3000);
x.add(function(){
    console.log('bye');
    console.log(+new Date() - now);
});

x.run();

참고 : 경고를 사용하면 경고를 닫을 때까지 자바 스크립트 실행이 중단됩니다. 요청한 것보다 더 많은 코드가있을 수 있지만 이것은 재사용 가능한 강력한 솔루션입니다.