JavaScript:For 循环超时

IT技术 javascript settimeout
2021-01-12 07:04:08

我希望我的 for 循环不应该立即执行,而是在每次迭代后等待超时。例如:

for(var i=0; i<10; i++) {
    console.log(i);
    //wait for 1000
}

我在堆栈溢出上找到了许多解决方案,如下所示:

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

但在所有实现中,循环最初等待 3000 毫秒,然后立即执行整个for循环。有没有办法在等待 1000 毫秒后调用每次迭代。

6个回答

你可以用简单的数学来解决这个问题:

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

1000ms : 0
4000ms : 1
7000ms : 2
10000ms : 3
13000ms : 4
...


关注评论

看来你的要求有点模糊。如果你想在最后一次超时后做一些事情,你可以设置一个限制并比较当前索引:

var limit = 10
for (var i=0;i<=limit;i++) {
   (function(ind) {
       setTimeout(function(){
           console.log(ind);
           if(ind === limit){
               console.log('It was the last one');
           }
       }, 1000 + (3000 * ind));
   })(i);
}

小提琴:http : //jsfiddle.net/Tn4A7/


我想我知道你想要什么......

它只是简单地做

for (var i=0;i<=10;i++) {
   (function(ind) {
       setTimeout(function(){console.log(ind);}, 1000 * ind);
   })(i);
}
@FabianMontossi(i)立即调用前面括号内的匿名函数。在这种情况下,(function(ind) {...})(i)创建一个新函数,该函数接受一个参数ind,然后i 进入循环的下一次迭代之前立即使用 的值调用它所以如果值发生i变化,ind不会。这称为 IIFE,您可以在此处阅读更多信息:developer.mozilla.org/en-US/docs/Glossary/IIFE
2021-03-26 07:04:08
@Karl-André Gagnon 你介意告诉我为什么 (i); ???我已经理解了一切,除了那部分,我的意思是,我不明白它在那里做什么,它做了什么,或者为什么在那里。如果我只是把这个: for (var i=0;i<=10;i++) { (i); 显然它没有做任何事情,但是,在我压制的功能中,它也不应该修改任何内容,因为它没有在任何地方提到......我的意思是,“(i);” 在任何情况下都不应该做任何事情。我完全迷失了(i);如果你能澄清我,或者告诉我要寻找什么(这是最糟糕的部分),我将不胜感激。
2021-04-03 07:04:08
@Karl-AndréGagnon - 我知道,我知道,这就是我开始为你免责的原因
2021-04-04 07:04:08
我不确定这是否正是 OP 想要的(尽管它肯定更好)。我认为他们想等到所有超时都触发然后继续。
2021-04-06 07:04:08
也许这并不重要 - 这当然不是 Gagnon 的错,这就是问题提出的方式 - 但是您确实意识到脚本的执行甚至在第一个 console.log 之前就已经过了 for 循环,对吗?参见:jsfiddle.net/WXkLK
2021-04-12 07:04:08

不要在 loops 内创建函数,而是:

(function fiveSeconds  (n) {

  if (n < 5) setTimeout(function () {  
    fiveSeconds ( n ); // Redo if n < 5 (and pass n)
  }, 1000);
  
  console.log( n++ );

} (0)); // Initialize. n is 0

以上将以1 秒的间隔记录0 - 5 之间的十个数字

现代浏览器(和 IE10+)

(function fiveSeconds (n) {

  console.log( n++ );

  if (n <= 5) setTimeout( fiveSeconds, 1000, n ); // Redo if n <= 5 (and pass n)
  
} (0)); // Initialize. n is 0

为什么不使用这样的东西:

var i = 0
var id = window.setInterval(function(){
    if(i >= 10) {
        clearInterval(id);
        return;
    }

    console.log(i);
    i++;
}, 1000)

这有效:

function initiateTimeOut(i) {
  setTimeout(function() { doStuff(i) }, 30);
}
function doStuff(i) {
    console.log(i);
    i++;
    if (i <= 10) {
        initiateTimeOut(i); 
    }
}

initiateTimeOut(0);

这样你只会i在你的函数执行时增加,我相信这就是你要找的。

小提琴示例:http : //jsfiddle.net/My7Zg/


或者,甚至更短(http://jsfiddle.net/My7Zg/1/):

function customLoop(i) {
    console.log(i);
    i++;
    if (i<=10) {setTimeout(function(){customLoop(i);},1000);}
}
customLoop(0);
这实际上挂了我的电脑。
2021-03-14 07:04:08
是的,这很糟糕。请修改或删除。
2021-03-14 07:04:08
@MarcellFülöp 现在正在修改。
2021-03-22 07:04:08
1)我怀疑这是否如您所想,2)这不是 OP 想要的。
2021-03-31 07:04:08
实际上,您要做的就是锁定浏览器。您将不断循环设置更多超时,直到您的浏览器放弃。
2021-04-11 07:04:08
for (var i=0;i<=10;i++) {
   (function(ind) {
       setTimeout(function(){console.log((ind + 1)*1000, ':', ind);}, 1000 * (ind+1) );
   })(i);
}

输出:

1000 : 0
2000 : 1
3000 : 2
4000 : 3
5000 : 4
6000 : 5
7000 : 6
8000 : 7
9000 : 8
10000 : 9
11000 : 10

工作演示