programing

JavaScript 루프에 지연을 추가하려면 어떻게 해야 하나요?

procenter 2022. 12. 29. 21:43
반응형

JavaScript 루프에 지연을 추가하려면 어떻게 해야 하나요?

에 딜레이/슬립을 .while 디세이블로그:

이렇게 해봤어요.

alert('hi');

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

첫 번째 시나리오입니다.alert('hi') 3초 후에 3초 기다린다.alert('hello')되지만, 「」는 표시됩니다.alert('hello')계속 반복됩니다.

것은 그입니다.alert('hello') 뒤에 요.alert('hi') 두 동안 돼요.alert('hello')기타 등등.

함수는 비블로킹이며 즉시 돌아갑니다.따라서 루프가 매우 빠르게 반복되고 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

ES7은 루프를 기다리는 데 더 좋은 방법입니다.

// Returns a Promise that resolves after "ms" Milliseconds
const timer = ms => 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();

이 에 했을 때awaitpart는 타임아웃을 설정하고 의 실행을 중지합니다.그런 다음 타임아웃이 완료되면 해당 시점에서 실행이 계속됩니다.이는 (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와 최신 브라우저에서 지원되고 있지만 Babel을 사용하여 변환하고 싶을 수 있습니다.JS는 어디서나 사용할 수 있도록 합니다.

ES6 를 사용하고 있는 경우는, for 루프를 사용해 이것을 실현할 수 있습니다.

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

이 되어 있습니다.i반복에 대해 타임아웃이 + 1000 이전임을 의미합니다.이렇게 하면 전달되는 것은setTimeout그게 바로 우리가 원하는 거야

다음과 같은 방법을 사용해 보십시오.

var i = 0, howManyTimes = 10;

function f() {
  console.log("hi");
  i++;
  if (i < howManyTimes) {
    setTimeout(f, 3000);
  }
}

f();

또 다른 방법은 타임아웃 시간을 곱하는 것이지만 이는 sleep과 같지 않다는 점에 유의하십시오.루프 후의 코드는 즉시 실행되며, 콜백 함수의 실행만 지연됩니다.

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();

주의: 경보를 사용하면 경보를 닫을 때까지 javascript 실행이 중지됩니다.요청하신 것보다 더 많은 코드일 수도 있지만, 이는 재사용 가능한 강력한 솔루션입니다.

나는 아마도 그것을 사용할 것입니다.setInterval 이렇게요.

var period = 1000; // ms
var endTime = 10000;  // ms
var counter = 0;
var sleepyAlert = setInterval(function(){
    alert('Hello');
    if(counter === endTime){
       clearInterval(sleepyAlert);
    }
    counter += period;
}, period);

만들 수 요.sleep" " "를 "setTimeout 기능을 「 」를 할 수 있습니다.async/await for루프 제어 플로우

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

(async () => {
  for (let i = 0; i < 10; i++) {
    console.log(i);
    await sleep(1000);
  }

  console.log("done");
})();

에서는 '노드'를 사용할 수 .timers/promises비문명화 단계를 피하기 위해(이 기능이 이전 노드 버전에서 지원되지 않는 경우 위의 코드도 동일하게 작동합니다).

const {setTimeout: sleep} = require("timers/promises");

// same code as above

어쨌든 JS는 싱글 스레드이기 때문에 타임아웃이 비동기적이라는 것은 좋은 일입니다.그렇지 않은 경우 브라우저는 UI를 다시 그릴 수 없기 때문에 사용자의 인터페이스가 정지됩니다.

내 생각에 루프의 지연을 추가하는 가장 간단하고 우아한 방법은 다음과 같습니다.

names = ['John', 'Ana', 'Mary'];

names.forEach((name, i) => {
 setTimeout(() => {
  console.log(name);
 }, i * 1000);  // one sec interval
});

ES6(ECMAScript 2015)에서는 발생기 및 간격으로 지연을 반복할 수 있습니다.

ECMAScript 6의 신기능인 제너레이터는 일시정지 후 재개할 수 있는 기능입니다.genFunc를 호출해도 실행되지 않습니다.대신 genFunc의 실행을 제어할 수 있는 이른바 생성기 개체를 반환합니다.genFunc()는 처음에 본문의 선두에서 일시정지됩니다.genObj.next() 메서드는 genFunc의 실행을 다음 산출까지 계속합니다.(ES6 탐색)


코드 예:

let arr = [1, 2, 3, 'b'];
let genObj = genFunc();

let val = genObj.next();
console.log(val.value);

let interval = setInterval(() => {
  val = genObj.next();
  
  if (val.done) {
    clearInterval(interval);
  } else {
    console.log(val.value);
  }
}, 1000);

function* genFunc() {
  for(let item of arr) {
    yield item;
  }
}

따라서 ES6를 사용하고 있다면, 이것이 지연으로 루프를 실현하는 가장 우아한 방법이라고 생각합니다.

블루버드랑 같이 해요.Promise.delay그리고 재귀.

function myLoop(i) {
  return Promise.delay(1000)
    .then(function() {
      if (i > 0) {
        alert('hello');
        return myLoop(i -= 1);
      }
    });
}

myLoop(3);
<script src="//cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.4/bluebird.min.js"></script>

ES6 에서는, 다음과 같이 할 수 있습니다.

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

ES5에서는 다음 작업을 수행할 수 있습니다.

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

이,입니다.let 또는 할 수 .는 '과는 .var키워드: 변수를 글로벌하게 정의하거나 블록스코프에 관계없이 함수 전체에 로컬로 정의합니다.

기능이 없는 솔루션

파티에는 조금 늦었지만, 기능을 사용하지 않고 해결 방법이 있습니다.

alert('hi');

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

내 의견도 여기에 올릴까 해서요.이 함수는 지연과 함께 반복 루프를 실행합니다.이 jsfiddle을 보세요.기능은 다음과 같습니다.

function timeout(range, time, callback){
    var i = range[0];                
    callback(i);
    Loop();
    function Loop(){
        setTimeout(function(){
            i++;
            if (i<range[1]){
                callback(i);
                Loop();
            }
        }, time*1000)
    } 
}

예를 들어 다음과 같습니다.

//This function prints the loop number every second
timeout([0, 5], 1, function(i){
    console.log(i);
});

다음과 같습니다.

//This function prints the loop number instantly
for (var i = 0; i<5; i++){
    console.log(i);
}

로는 to가 to to to to to to to to to to 。setTimeout이치노, 「」를 합니다.Promise타임아웃을 설정하다

var looper = async function () {
  for (var start = 1; start < 10; start++) {
    await new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("iteration: " + start.toString());
        resolve(true);
      }, 1000);
    });
  }
  return true;
}

그런 다음 이렇게 실행하라고 합니다.

looper().then(function(){
  console.log("DONE!")
});

비동기 프로그래밍을 잘 이해할 수 있도록 시간을 내 주세요.

10년 전에 받아들여진 답변에 더하여, 보다 현대적인 Javascript를 사용할 수 있습니다.async/await/Promise()또는 제너레이터 기능을 사용하여 올바른 동작을 수행합니다.(다른 답변에서 제시된 잘못된 동작은 다음 질문에 대한 "승인" 여부에 관계없이 일련의 경고를 3초 동안 설정하는 것입니다.alert()- 또는 수중에 있는 작업 완료)

사용.async/await/Promise():

alert('hi');

(async () => {
  for(let start = 1; start < 10; start++) {
    await new Promise(resolve => setTimeout(() => {
      alert('hello');
      resolve();
    }, 3000));
  }
})();

제너레이터 기능 사용:

alert('hi');

let func;

(func = (function*() {
  for(let start = 1; start < 10; start++) {
    yield setTimeout(() => {
      alert('hello');
      func.next();
    }, 3000);
  }
})()).next();

RxJS 연산자를 사용할 수 있습니다. interval매회 정수를 방출하다xseconds, 및take는, 이러한 번호를 송신하는 회수를 지정합니다.

Rx.Observable
  .interval(1000)
  .take(10)
  .subscribe((x) => console.log(x))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.lite.min.js"></script>

    var startIndex = 0;
    var data = [1, 2, 3];
    var timeout = 1000;

    function functionToRun(i, length) {
      alert(data[i]);
    }

    (function forWithDelay(i, length, fn, delay) {
      setTimeout(function() {
        fn(i, length);
        i++;
        if (i < length) {
          forWithDelay(i, length, fn, delay);
        }
      }, delay);
    })(startIndex, data.length, functionToRun, timeout);

Daniel Vassallo의 답변 수정 버전으로, 함수를 보다 재사용할 수 있도록 변수를 파라미터로 추출했습니다.

먼저 몇 가지 필수 변수를 정의합니다.

var startIndex = 0;
var data = [1, 2, 3];
var timeout = 3000;

다음으로 실행할 기능을 정의해야 합니다.이것은 i, 루프의 현재 인덱스 및 루프의 길이를 전달합니다(필요한 경우).

function functionToRun(i, length) {
    alert(data[i]);
}

자가 실행 버전

(function forWithDelay(i, length, fn, delay) {
   setTimeout(function () {
      fn(i, length);
      i++;
      if (i < length) {
         forWithDelay(i, length, fn, delay); 
      }
  }, delay);
})(startIndex, data.length, functionToRun, timeout);

기능 버전

function forWithDelay(i, length, fn, delay) {
   setTimeout(function () {
      fn(i, length);
      i++;
      if (i < length) {
         forWithDelay(i, length, fn, delay); 
      }
  }, delay);
}

forWithDelay(startIndex, data.length, functionToRun, timeout); // Lets run it

이것만 먹어봐

 var arr = ['A','B','C'];
 (function customLoop (arr, i) {
    setTimeout(function () {
    // Do here what you want to do.......
    console.log(arr[i]);
    if (--i) {                
      customLoop(arr, i); 
    }
  }, 2000);
})(arr, arr.length);

결과

A // after 2s
B // after 2s
C // after 2s

다음으로 특정 조건에서 중단되는 지연을 가진 무한 루프를 작성하는 방법을 나타냅니다.

  // Now continuously check the app status until it's completed, 
  // failed or times out. The isFinished() will throw exception if
  // there is a failure.
  while (true) {
    let status = await this.api.getStatus(appId);
    if (isFinished(status)) {
      break;
    } else {
      // Delay before running the next loop iteration:
      await new Promise(resolve => setTimeout(resolve, 3000));
    }
  }

여기서 중요한 것은 타임아웃으로 해결되는 새로운 Promise를 만들고 해결되기를 기다리는 것입니다.

당연히 비동기/대기 지원이 필요합니다.노드 8에서 동작합니다.

일반적으로 "normal loops forget normal"을 사용하고 "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: (setTimeOut)의 실제 동작은 "3개의 bla bla bla bla가 같은 순간에 카운트다운을 시작합니다"로 시작되므로 다른 타임아웃을 설정하여 실행을 준비합니다.

PS 2: 타이밍 루프의 예이지만, 이벤트를 사용할 수 있는 응답 루프의 경우, 약속 비동기 대기.

   let counter =1;
   for(let item in items) {
        counter++;
        setTimeout(()=>{
          //your code
        },counter*5000); //5Sec delay between each iteration
    }
const autoPlayer = (arr = [1, 2, 3, 4, 5]) => {
  // Base case:
  if (arr.length < 1) return

  // Remove the first element from the array.
  const item = arr.shift()

  // Set timout 
  setTimeout(() => {
    console.log('Hello, world!', item)  // Visualisation.
    autoPlayer() // Call function again.
  }, 1000) // Iterate every second.
}

이 게시물이 아주 오래된 건 알지만, 이 코드는 "루프"되고 재귀적 방법으로 지연을 추가합니다.다른 사람의 다양한 코멘트를 읽고 루프 자체를 반복하는 것을 '실제로' 지연시킬 수는 없다고 생각합니다. 함수는 (이예에서는기본적으로 함수는 배열을 받아들입니다(이 예에서는).setTimeout자바스크립트는, 「 」, 「 」의 타이머가 「 」, 「 」, 「 」의 타이머에 됩니다.setTimeout기능은 만료되지만 콜마다 베이스 케이스에 도달할 때까지 어레이가 작아집니다.이게 누구에게도 도움이 됐으면 좋겠어요.

비동기 대기 기능을 사용하여 실제 지연을 발생시키는 단순한 한 줄 솔루션:

다음(어나니머스) 함수는 다른 타임아웃을 가진 여러 setTimeout 대신 루프 간에 실제 지연을 생성하여 메모리를 혼란시킬 수 있습니다.

  • awaitnew Promise로로 합니다.resolve.
  • 은 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다.setTimeout90도입니다.에 됩니다.Promise.

(async () => {
  for (let i=0; i<100; i++) {
    await new Promise((resolve) => {setTimeout(() => {document.write(`${i} `); resolve(true)}, 90)});
  }
})()

/* 
  Use Recursive  and setTimeout 
  call below function will run loop loopFunctionNeedCheck until 
  conditionCheckAfterRunFn = true, if conditionCheckAfterRunFn == false : delay 
  reRunAfterMs miliseconds and continue loop
  tested code, thanks
*/

function functionRepeatUntilConditionTrue(reRunAfterMs, conditionCheckAfterRunFn,
 loopFunctionNeedCheck) {
    loopFunctionNeedCheck();
    var result = conditionCheckAfterRunFn();
    //check after run
    if (!result) {
        setTimeout(function () {
            functionRepeatUntilConditionTrue(reRunAfterMs, conditionCheckAfterRunFn, loopFunctionNeedCheck)
        }, reRunAfterMs);
    }
    else  console.log("completed, thanks");    
            //if you need call a function after completed add code call callback in here
}

//passing-parameters-to-a-callback-function
// From Prototype.js 
if (!Function.prototype.bind) { // check if native implementation available
    Function.prototype.bind = function () {
        var fn = this, args = Array.prototype.slice.call(arguments),
            object = args.shift();
        return function () {
            return fn.apply(object,
              args.concat(Array.prototype.slice.call(arguments)));
        };
    };
}

//test code: 
var result = 0; 
console.log("---> init result is " + result);
var functionNeedRun = function (step) {           
   result+=step;    
       console.log("current result is " + result);  
}
var checkResultFunction = function () {
    return result==100;
}  

//call this function will run loop functionNeedRun and delay 500 miliseconds until result=100    
functionRepeatUntilConditionTrue(500, checkResultFunction , functionNeedRun.bind(null, 5));

//result log from console:
/*
---> init result is 0
current result is 5
undefined
current result is 10
current result is 15
current result is 20
current result is 25
current result is 30
current result is 35
current result is 40
current result is 45
current result is 50
current result is 55
current result is 60
current result is 65
current result is 70
current result is 75
current result is 80
current result is 85
current result is 90
current result is 95
current result is 100
completed, thanks
*/

어레이를 루프하기 위해 사용하는 함수는 다음과 같습니다.

function loopOnArrayWithDelay(theArray, delayAmount, i, theFunction, onComplete){

    if (i < theArray.length && typeof delayAmount == 'number'){

        console.log("i "+i);

        theFunction(theArray[i], i);

        setTimeout(function(){

            loopOnArrayWithDelay(theArray, delayAmount, (i+1), theFunction, onComplete)}, delayAmount);
    }else{

        onComplete(i);
    }
}

다음과 같이 사용합니다.

loopOnArrayWithDelay(YourArray, 1000, 0, function(e, i){
    //Do something with item
}, function(i){
    //Do something once loop has completed
}

이 스크립트는 대부분의 경우에 유효합니다.

function timer(start) {
    setTimeout(function () { //The timer
        alert('hello');
    }, start*3000); //needs the "start*" or else all the timers will run at 3000ms
}

for(var start = 1; start < 10; start++) {
    timer(start);
}

<!DOCTYPE html>
<html>
<body>

<button onclick="myFunction()">Try it</button>

<p id="demo"></p>

<script>
function myFunction() {
    for(var i=0; i<5; i++) {
    	var sno = i+1;
       	(function myLoop (i) {          
             setTimeout(function () {   
             	alert(i); // Do your function here 
             }, 1000*i);
        })(sno);
    }
}
</script>

</body>
</html>

이거 드셔보세요.

var icount=0;
for (let i in items) {
   icount=icount+1000;
   new beginCount(items[i],icount);
}

function beginCount(item,icount){
  setTimeout(function () {

   new actualFunction(item,icount);

 }, icount);
}

function actualFunction(item,icount){
  //...runs ever 1 second
 console.log(icount);
}

언급URL : https://stackoverflow.com/questions/3583724/how-do-i-add-a-delay-in-a-javascript-loop

반응형