【问题标题】:setTimeout happens only once in a loop expressionsetTimeout 在循环表达式中只发生一次
【发布时间】:2015-07-09 06:27:57
【问题描述】:

这是一个例子:

function func1()
{
   setTimeout(function(){doSomething();}, 3000);
}
for(i=0;i<10;i++)
{
   func1();
}

在执行之后,延迟只发生在第一个循环中,但它没有发生在那个“for”表达式的其余循环中。

我想让延迟发生在所有循环中,而不仅仅是第一次。
我的代码有什么问题?

【问题讨论】:

  • 一切都应该发生,但同时发生。
  • 所有doSomethings 都被安排在它们被安排的3秒后执行。由于它们一个接一个地被安排,它们之间几乎没有任何时间,它们将在 3 秒后执行,它们之间几乎没有任何时间。你期望会发生什么?如果您希望它们在每个 3 秒之间执行,请将它们安排在 3000、6000、9000... 或将下一个安排在当前的末尾,而不是在它们之外的循环中。
  • 你为什么不增加一个计数器并在你的 doSomething 函数中吐出它来看看它被触发了多少次? (不确定时间戳是否会有所帮助,因为它们都可以打印相同的时间戳)
  • @Amadan 现在我明白了,毫秒是从执行页面的时间开始的,而不是从浏览器读取特定行的时间,这是一个误解,谢谢
  • 不,它来自执行setTimeout。但是所有的setTimeout 调用都是循环执行的,它们之间没有延迟。

标签: javascript loops


【解决方案1】:

您正在安排 10 个电话,但问题是所有电话都安排在同一时间,即 3 秒后。

如果你想逐步调用它们,那么你需要增加每次调用的延迟。

解决方案是将延迟单元值传递给 func1 之类的

function func1(i) {
  setTimeout(function() {
    doSomething();
  }, i * 500);//reduced delay for testing
}
for (i = 0; i < 10; i++) {
  func1(i + 1);
}

var counter = 0;

function doSomething() {
  snippet.log('called: ' + ++counter)
}
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<!-- To show result in the dom instead of console, only to be used in the snippet not in production -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

【讨论】:

  • 或者可以使用setInterval
  • 有趣的 sn-p 东西
  • @mplungjan 它是从T.J. Crowder借来的
  • 嗯,是的.. 有人刚刚回答了 setInterval fiddle 。它更快,但使用这个答案我让任务变得非常清楚对我来说,因为我的任务中有一个可变的时间戳和其他东西
【解决方案2】:

循环将安排 10 次超时,全部在 3 秒后完成。你可以使用递归setTimeout:

function loopAsync(delay, n, f) {
  setTimeout(function() {
    if (n > 0) {
      f()
      loopAsync(delay, n - 1, f)
    }
  }, delay)
}

loopAsync(3000, 10, doSomething)

【讨论】:

【解决方案3】:

发生的事情是你调用了 10 次(没有延迟)func1() 然后你同时拥有 10 个函数,解决方案很简单,使用 setInterval,这是一个 fiddle

【讨论】:

  • 工作,谢谢。你应该把你的代码复制到这里,这样如果 JSFiddle 不再存在,那么至少我们有冷硬代码。
【解决方案4】:

async.js:

async.timesSeries(5, function (n, next) {
    setTimeout(function(){
        doSomething();
        next();
    }, 3000);
});

【讨论】:

    【解决方案5】:

    如果您想以恒定延迟进行迭代,恕我直言,您最好使用setInterval

    var loops = 9,
        intervalId = setInterval(function () {
            // My super code goes here
            console.log(loops);
            loops-- <= 0 && (clearInterval(intervalId));
        }, 3000);
    

    我为你做了一个jsfiddle

    【讨论】:

      【解决方案6】:

      for 循环连续运行,因此每次调用都是该调用的 3000 毫秒。导致两次通话之间没有延迟。 为了更好地理解,在时间 t 和 t + 1 循环调用 func1。所以它将在 t + 3000 和 T + 3001 执行,没有区别。

      您可以尝试以下方法:-

      function func1(i){
           setTimeout(function(){doSomething();}, i * 3000);
       }
      for(i=i;i<=10;i++){
        func1(i);
      }
      

      注意:- 循环初始化为 i = 1。

      【讨论】:

        【解决方案7】:

        这是因为setTimeout() 函数是非阻塞的。因此,您的 setTimeout() 函数仅在第一次运行。

        试试这个代码...

        var i = 1;
            function func1(){
                setTimeout(function(){
                    doSomething();
                    i++;
                    if(i < 10){
                        func1();
                    }
                }, 3000);
            }
        func1();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-13
          • 1970-01-01
          • 2021-12-14
          相关资源
          最近更新 更多