【问题标题】:How to use setInterval function within for loop如何在 for 循环中使用 setInterval 函数
【发布时间】:2011-12-06 15:19:27
【问题描述】:

我正在尝试在给定可变项目列表的情况下运行多个计时器。代码如下所示:

var list = Array(...);

for(var x in list){
    setInterval(function(){
        list[x] += 10;
        console.log(x + "=>" + list[x] + "\n");
    }, 5 * 1000);
}

上面代码的问题是,唯一被更新的值是列表末尾的项目,乘以列表中的项目数。

谁能提供解决方案和解释,让我知道为什么会这样?

【问题讨论】:

    标签: javascript for-loop closures setinterval


    【解决方案1】:

    所以,有几件事:

    1. 最重要的是,您传递给setInterval() 的回调函数维护了对x 的引用,而不是x 的快照值,因为它在每次特定迭代期间都存在。因此,随着x 在循环中发生更改,它也会在每个回调函数中更新。
    2. 此外,for...in 用于枚举对象属性,并且在用于数组时可以behave unexpectedly
    3. 更重要的是,我怀疑你真的想要setTimeout() 而不是setInterval()

    您可以通过向setTimout() 提供额外的参数来将参数传递给您的回调函数:

    var timeoutID = window.setTimeout(func, delay<b>, [param1, param2, ...]</b>);

    数字将按值而不是引用传递。这是一个例子:

    var list = [1,2,3,4];
    
    for (var x = 0, ln = list.length; x < ln; x++) {
      setTimeout(function(y) {    
        console.log("%d => %d", y, list[y] += 10);
      }, x * 500, x); // we're passing x
    }

    【讨论】:

    • 是的,我可以推荐阅读这篇文章:blog.morrisjohns.com/javascript_closures_for_dummies。最重要的是,循环中的 setTimeout 可能不是他想要做的,因为所有回调将同时触发,它们不会交错。
    • OP 并不“需要一个闭包”,恰恰相反——它有一个需要避免的对 x 的闭包(你的答案实际上是这样做的)。它保持对 list 的关闭。
    【解决方案2】:

    var list = [1, 2, 3, 4, 5];
    
    for (var i = 0, len = list.length; i < len; i += 1) {
        (function(i) {
            setInterval(function() {
                list[i] += 10;
                console.log(i + "=>" + list[i] + "\n");
            }, 5000)
        })(i);
    }

    这是工作代码:

    var list = [1, 2, 3, 4, 5];
    
    for (var i = 0, len = list.length; i < len; i += 1) {
        (function(i) {
            setInterval(function() {
                list[i] += 10;
                console.log(i + "=>" + list[i] + "\n");
            }, 5000)
        })(i);
    }
    

    这里的索引i 存储在一个匿名函数中,因此它不会被连续循环覆盖。代码中的setInterval 函数仅保留对i 的最后一个值的引用。

    【讨论】:

    • 优秀的解决方案!一个小提示:在循环中可以更改的任何内容都可以传递给匿名函数,而不仅仅是索引。
    • 非常感谢!使用匿名功能完美!
    【解决方案3】:

    您不必在 setInterval 语句中使用 for 循环。试试这个:

    var list = Array(...);
    var x = 0;
    
    setInterval(function() {
    
        if (x < list.length;) {
            list[x] += 10;
            console.log(x+"=>"+list[x]);
        }
    
        else return;
    
        x++;
    }, 5000);
    

    【讨论】:

      【解决方案4】:

      如果你有 JSON 数组和 jQuery,你可以使用:

      $.each(jsonArray, function(i, obj) {
          setInterval( function() {
              console.log(i+' '+obj);
          }, 10);
      });
      

      【讨论】:

        【解决方案5】:

        我不知道如何使用 for 循环来执行此操作,但此处的代码将按时间间隔打印出数组中的每个元素:

        function displayText(str) {
           $('.demo').append($('<div>').text(str));
        }
        var i = 0;
        
        var a = [12, 3, 45, 6, 7, 10];
        
        function timedLoop() {
        setTimeout(function () {
            displayText(a[i]);
            i++;
            if(i < a.length) {
                timedLoop();
            }
        }, 2000)
        }
        
        timedLoop();
        

        使用一点 jquery 在浏览器中显示它。

        【讨论】:

          【解决方案6】:

          您可以将forEachsetTimeout 组合使用,以使用区间循环遍历数组。

          let modes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
          let interval = 1000; //one second
          modes.forEach((mode, index) => {
          
            setTimeout(() => {
              console.log(mode)
            }, index * interval)
          })

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-02
            • 1970-01-01
            • 2021-11-18
            • 1970-01-01
            • 2020-12-26
            • 2020-09-11
            • 1970-01-01
            • 2020-06-03
            相关资源
            最近更新 更多