[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)); }
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();
참고 : 경고를 사용하면 경고를 닫을 때까지 자바 스크립트 실행이 중단됩니다. 요청한 것보다 더 많은 코드가있을 수 있지만 이것은 재사용 가능한 강력한 솔루션입니다.