【问题标题】:How to create pause or delay in FOR loop?如何在 FOR 循环中创建暂停或延迟?
【发布时间】:2012-04-20 23:20:48
【问题描述】:

我正在开发一个网站,我需要在其中创建暂停或延迟。
所以请告诉我如何在javascriptjQuery 中的for 循环中创建暂停或延迟

这是一个测试示例

 var s = document.getElementById("div1");
 for (i = 0; i < 10; i++) {
     s.innerHTML = s.innerHTML + i.toString();
     //create a pause of 2 seconds.
  }

【问题讨论】:

  • 您不能在网络浏览器中“暂停”JavaScript。但是,您可以使用所有浏览器中可用的 setTimeout()setInterval() API 设置计时器并让代码稍后执行。
  • tldr:如果您想利用异步性,您必须将代码转换为递归、连续传递样式。 (好吧,或者像 Guffa 那样使用聪明的把戏)
  • 这能回答你的问题吗? How do I add a delay in a JavaScript loop?

标签: javascript jquery for-loop


【解决方案1】:

您不能在函数中使用延迟,因为这样您对元素所做的更改将在您退出函数之前显示出来。

使用setTimeout 稍后运行代码片段:

var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {

  // create a closure to preserve the value of "i"
  (function(i){

    window.setTimeout(function(){
      s.innerHTML = s.innerHTML + i.toString();
    }, i * 2000);

  }(i));

}

【讨论】:

  • @Pointy:好点。我添加了一个闭包来保存每个值。
  • @Guffa:你的括号在你的函数执行中是关闭的
  • @BrokenGlass:不,他们不是。代码运行得很好。 jsfiddle.net/Guffa/PcuxY
  • 我有点困惑,如果闭包“保留i 的值”,为什么i * 2000 计算的不等于0,因为0 是第一个值i 的?或者,如果i 在每次迭代中递增,为什么每次innerHTML 更新之间的持续时间没有同样增加?
  • 当我在循环的第一行和 iife 的第一行登录时更令人困惑:它们都立即记录`0-9`。我知道已经很久了,但是你能解释一下这里发生了什么吗? jsbin.com/foqineciva/edit?html,js,output
【解决方案2】:
var wonderfulFunction = function(i) {
   var s = document.getElementById("div1"); //you could pass this element as a parameter as well
   i = i || 0;
   if(i < 10) {
      s.innerHTML = s.innerHTML + i.toString();

      i++;
      //create a pause of 2 seconds.
      setTimeout(function() { wonderfulFunction(i) }, 2000);          
   }
}

//first call
wonderfulFunction(); //or wonderfulFunction(0);

您不能暂停 javascript 代码,整个语言都是为处理事件而设计的,我提供的解决方案让您可以延迟执行函数,但执行永远不会停止。

【讨论】:

  • 这会有很大的问题,因为所有的超时函数共享相同的“i”值。他们都会将 11 传递给“wonderfulFunction”。
  • for 循环有什么用?鉴于它总是执行break,使用if 语句不是更直接吗?出于同样的原因,我不明白你为什么需要内部函数......
  • @nnnnnn 因为我不假思索地编辑了答案。起初我采用了不同的方法,然后我将其更改为使用 clousure。写的方式for没用,编辑时间:)。
  • 对不起,我的 JS 语法不是最好的。 i = i || 0; 这行是什么意思?
  • @VictorResnov 表示“如果i 的值为真,则将i 分配给自身,否则将其分配给0”developer.mozilla.org/en-US/docs/Glossary/Truthy
【解决方案3】:

我都试过了,但我认为这个代码更好,它是非常简单的代码。

var s = document.getElementById("div1");
var i = 0;
setInterval(function () {s.innerHTML = s.innerHTML + i.toString();  i++;}, 2000);

【讨论】:

    【解决方案4】:

    如果你想在 FOR 循环中创建暂停或延迟,唯一真正的方法是

    while (true) {
        if( new Date()-startTime >= 2000) {
            break;
        }
    }
    

    startTime 是运行 while 之前的时间 但是这种方法会导致浏览器变得很慢

    【讨论】:

      【解决方案5】:

      不可能在 for 循环中直接暂停 Javascript 函数,然后在该点恢复。

      【讨论】:

        【解决方案6】:

        你应该这样做

        var i = 0;
        setTimeout(function() {
           s.innerHTML = s.innerHTML + i.toString();
           i++;
        },2000);
        

        【讨论】:

          【解决方案7】:

          以下代码是您可以在 JS 中执行的伪多线程示例,它大致是您如何延迟循环的每次迭代的示例:

          var counter = 0;
          
          // A single iteration of your loop
          // log the current value of counter as an example
          // then wait before doing the next iteration
          function printCounter() {
              console.log(counter);
              counter++;
              if (counter < 10)
                  setTimeout(printCounter, 1000);
          }
          
          // Start the loop    
          printCounter();
          

          【讨论】:

            【解决方案8】:

            虽然其他几个答案都可以,但我发现代码不太优雅。 Frame.js 库正是为了解决这个问题而设计的。使用 Frame 你可以这样做:

            var s = document.getElementById("div1");
            for (i = 0; i < 10; i++) {
               Frame(2000, function(callback){ // each iteration would pause by 2 secs
                  s.innerHTML = s.innerHTML + i.toString();
                  callback();
               }); 
            }
            Frame.start();
            

            在这种情况下,它与使用 setTimeout 的示例几乎相同,但 Frame 提供了很多优势,特别是如果您尝试执行多个或嵌套超时,或者有一个更大的 JS 应用程序需要超时在里面工作。

            【讨论】:

            • 和使用 setTimeout(function(){ alert('Foo'); },2000); 不完全一样;
            【解决方案9】:

            我正在执行一个需要访问外部对象属性的函数。所以,Guffa 解决方案中的关闭对我不起作用。我找到了nicosantangelo 解决方案的变体,只需将 setTimeout 包装在 if 语句中,这样它就不会永远运行。

                var i = 0;
                function test(){
            
                    rootObj.arrayOfObj[i].someFunction();
                    i++;
                    if( i < rootObj.arrayOfObj.length ){
                        setTimeout(test, 50 ); //50ms delay
                    }
            
                }
                test();
            

            【讨论】:

              【解决方案10】:

              我发现的方法是简单地使用setInterval() 来循环。这是我的代码示例:

              var i = 0;
              var inte = setInterval(() => {
                  doSomething();
              
                  if (i == 9) clearInterval(inte);
                  i++;
              }, 1000);
              
              function doSomething() {
                  console.log(i);
              };
              

              从 0 到 9 循环,在每次迭代之间等待 1 秒。

              输出:

              0 1 2 3 4 5 6 7 8 9
              

              【讨论】:

                【解决方案11】:

                无法暂停循环。但是,您可以使用 setTimeout() 函数延迟代码片段的执行。无论如何暂停整个执行是没有多大意义的。

                【讨论】:

                • “无论如何暂停整个执行过程没有多大意义” - 谁说的?这可能并不常见,但您可能有正当理由想要这样做。
                【解决方案12】:

                我使用 do...while 循环在我的代码中延迟关闭太快的模式对话框。

                your stuff....
                
                var tNow = Date.now();
                var dateDiff = 0;
                do {
                    dateDiff = Date.now() - tNow;
                } while (dateDiff < 1000); //milliseconds - 2000 = 2 seconds
                
                your stuff....
                

                【讨论】:

                  猜你喜欢
                  • 2020-04-15
                  • 2019-08-19
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多