【问题标题】:Looping through an array and delaying a function循环遍历数组并延迟函数
【发布时间】:2015-08-29 13:06:25
【问题描述】:

我正在尝试不断循环遍历一组数值,这些数值将作为触发另一个函数的延迟值传递给 setInterval 函数。这是我所拥有的:

HTML:

<p>On</p>

JavaScript:

$(document).ready(function(){
    var timing = [5000, 10000, 17000, 8000, 14000, 9000, 12000, 8000, 20000, 7000, 13000, 7000, 17000, 8000, 13000, 12000, 18000]
    //function to change
    function change(){
            var p = $("p").html();
            if(p === "On"){
                $("p").html("Off"); 
            } else {
                $("p").html("On");
            }
        }


    function myFunction(){
        for (var i = 0; i < timing.length; i++){
            var switchTime = timing[i];

            setInterval(function(){
                change(); 

            },switchTime);

        }
    } myFunction();

});

我想让更改功能在不同的延迟时间连续触发。现在,当我运行它时,时间似乎不正确。任何建议表示赞赏。谢谢!

【问题讨论】:

  • 究竟是什么不起作用?请描述您的期望和实际结果。
  • 根据时间数组中的数字,我希望更改函数每隔 5、10、17、8、14 秒等连续触发一次。现在的结果是 p 标签中的文本正在改变,但不是在这些间隔内。我怀疑我的函数会保留以前的时间间隔。
  • 这就是我的意思——你一遍又一遍地对同一个函数进行间隔,所以,当然你实际上可能有这些间隔,但这种印象是误导性的。
  • 在循环中我的 setInterval 之后立即调用 clearInterval 以确保更改函数接收到正确的数字是否有意义?
  • 可以工作,试一试!

标签: javascript arrays settimeout setinterval timedelay


【解决方案1】:

无论如何,使用循环是行不通的,因为很多setInterval(或setTimeout())会在几微秒内“立即”启动。
所以他们按照他们自己的timing[i] 所说的那样做他们的工作,但几乎是在同一时间!

相反,您必须仅在前一个步骤结束时启动每个步骤

这是一个工作示例(另请参阅this fiddle),我在其中添加了一些过程的视觉跟踪:

HTML:

<p id="on-off">On</p>
<p id="delay"></p>

Javascript:

$(document).ready(function(){
  var timing = [
    5000, 10000, 17000, 8000, 14000, 9000, 12000, 8000, 20000, 7000, 13000,
    7000, 17000, 8000, 13000, 12000, 18000
  ];
  function myFunction(i){
    i |= 0;
    if (i < timing.length - 1) {
      var switchTime = timing[i]
          $onOff = $('#onOff');
      $('#delay').html('i=' + i + ', delay=' + switchTime);
      $onOff.html($onOff.html() == 'On' ? 'Off' : 'On');
      setTimeout(
        function() {
          myFunction(i + 1);
        }, switchTime
      )
    } else {
      $('#delay').html('end');
    }
  }
  myFunction();
});

【讨论】:

  • 哇,这非常有帮助!非常感谢您的解释和小提琴。非常感谢。
【解决方案2】:

只需在setInterval 函数内增加变量i

function myFunction(){
    for (var i = 0; i < timing.length; ){
        var switchTime = timing[i];

        setInterval(function(){
            change(); 
           i++;
        },switchTime);

    }
}

【讨论】:

    【解决方案3】:

    使用setTimeout 而不是setInterval,因为您是在循环中执行此操作。 setInterval 将初始化一个计时器,该计时器以指定的延迟持续触发(例如,如果延迟为 5 秒,它将在 5、10、15 等处触发)。通过在您的迭代中使用setTimeout,定时器在指定延迟后每次迭代仅触发一次,并且下一次迭代为下一个延迟值初始化一个新定时器。

    【讨论】:

    • 对,我也试过 setTimeout,但我可以使用它连续循环遍历数组吗?一旦循环结束,我需要它重新开始。谢谢。
    【解决方案4】:

    我假设您在调用setInterval 时可能不会清除旧的间隔。根据https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval,您可能需要使用clearInterval 清除以前的间隔。特别是如果您对所有间隔都使用相同的方法,我认为您可能无法得到您想要的。所以:

    1. 创建区间,全局保存当前ID
    2. 当您的回调被调用时,使用clearInterval 函数清除当前间隔
    3. 重复

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 2019-01-17
      • 2016-10-02
      • 2014-06-04
      相关资源
      最近更新 更多