代码之家  ›  专栏  ›  技术社区  ›  Nick Lee

for循环中SetTimeout的意外行为

  •  2
  • Nick Lee  · 技术社区  · 7 年前

    我正在尝试按特定的时间间隔将数字记录到控制台。但是,实际发生的情况是,它等待设置的间隔,然后正常地注销所有内容。

    我尝试了两种不同的方法来创建一个闭包。但是对于延迟的console.log不做任何操作。

    function timeOutLoop(x){
       for(var i = 0; i<=x; i++){
        (function(n){
          setTimeout(function(){console.log(n)},5000)
        })(i)
    
         setTimeout(function(num){
          return function(){
            console.log(num)
          }
        }(i),1000)
      }
    }
    
    timeOutLoop(33)

    我的印象是,每个settimeout都将使用闭包提供的上下文进入事件队列。给出了什么?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Lolpez    7 年前

    function timeOutLoop(x){
        for(let i = 0; i<=x; i++){
            setTimeout(function(){console.log(i)},i * 1000);    
        }
    }
    timeOutLoop(33);

    这就是你要找的吗?从变化 var let 为了保持变量 i 在循环范围内完好无损。 More here about let vs var .

    也乘法 每秒钟打印1000次直到达到33次。

        2
  •  2
  •   r3zaxd1    7 年前

    设置超时是同时开始的,因此如果要一个接一个地开始超时,可以创建递归函数:

    function timeOutLoop(x, i=0){
       if(i<=x){
          console.log(i);
          i++;
          setTimeout(function(){timeOutLoop(x, i)},1000);
       }
    }
    timeOutLoop(33)
    

    您可以将超时值设置为任意值。

        3
  •  2
  •   Calvin Nunes    7 年前

    因为循环基本上是即时执行的,第一个循环不会有太大的差别,因为时间是毫秒,而第二个循环,它们都会在1秒后执行。

    使用这两种方法的组合,您可以实现:

     function timeOutLoop(x) {
      for(var i = 0; i <= x; i++) {
        setTimeout(function(num) {
          return function(){
              console.log(num);
          }
        }(i), i * 1000);
      }
    }
    
    timeOutLoop(33)