MMM Bacon
MMM Bacon

Reputation: 71

Looping through an array and delaying a function

I'm trying to continuously loop through an array of number values which will be passed to a setInterval function as the delay value that triggers another function. Here is what I have:

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();

});

I'd like to have the change function fire continuously at different delayed times. Right now the timing doesn't seem to be correct when I run it. Any suggestions are appreciated. Thanks!

Upvotes: 0

Views: 541

Answers (4)

cFreed
cFreed

Reputation: 4484

In any case, using a loop will not work, because a lot of setInterval (or setTimeout()) are "instantly" launched during a few microseconds.
So they do their job as stated by their own timing[i], but from almost the same time!

At the opposite, you must launch each step only when the previous one ends.

Here is a working example (see also this fiddle), where I added some visual tracking of the process:

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();
});

Upvotes: 1

bash.d
bash.d

Reputation: 13207

I assume you might not be clearing old intervals as you call setInterval. According to https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval you might need to clear previous intervals with clearInterval. Especially if you use the same method for all your intervals I think you might not get what you want. So:

  1. Create an interval, save the current ID globally
  2. When your callback being called, clear the current interval using clearInterval function
  3. Repeat

Upvotes: 1

marekful
marekful

Reputation: 15351

use setTimeout instead of setInterval because you are doing this in a loop. setInterval will initialise a timer that continuously fires at the specified delay (e.g. if delay if 5sec, it will fire at 5, 10, 15 and so forth). By using setTimeout in your iteration, the timer only fires once per iteration after the specified delay and the next iteration initialises a new timer for the next delay value.

Upvotes: 1

Vibhesh Kaul
Vibhesh Kaul

Reputation: 2613

Just increment the variable i inside the setInterval function.

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

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

    }
}

Upvotes: 1

Related Questions