Mona Coder
Mona Coder

Reputation: 6316

Setting count on set interval

I am working on the following code. Why is the interval happening only one time instead of 3, as expected on let x= 3?

Basically I need to repeat this loop/interval for 3 times but it is happening only once.

$(function() {
  let colors = ['red', 'blue', 'green']

  let x = 3;
  let interval = 6000;

  for (let i = 0; i < x; i++) {
    setTimeout(function() {
      $('body').css('background-color', colors[i]);
      backtoWhite();

    }, i * interval)
  }

  function backtoWhite() {
    setTimeout(function() {
      $('body').css('background-color', 'white');
    }, 3000);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 0

Views: 140

Answers (4)

poorly-written-code
poorly-written-code

Reputation: 1073

Your for loop is executing way faster than your timeout, so you're probably only seeing the first or last iteration. When dealing with timing, I'd recommend less variables and more recursion or callbacks.

Also, I'm assuming you want the time for each color to be constant, since red has an index of 0 and i * interval would mean you never see red.

let colors = ['red','white','blue','white','green','white'];

function SetBackgroundColor(colorIndex) {
    colorIndex = colorIndex >= colors.length - 1 ? 0 : ++colorIndex; //constrain index  
    
    $('body').css({'background-color': colors[colorIndex]}); //set color
    
    setTimeout(
      function() { SetBackgroundColor(colorIndex); }, //recursion
      colors[colorIndex] === 'white' ? 3000 : 6000); //select timeout
}

SetBackgroundColor(-1); //initialize
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p></p>

Upvotes: 0

Unmitigated
Unmitigated

Reputation: 89324

You can use setInterval to execute a function continuously whereas a setTimeout executes a function once after a specified delay (in milliseconds).

The documentation for setInterval states that:

The setInterval() method of the WindowOrWorkerGlobalScope mixin repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. It returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval().

The documentation for setTimeout states that:

The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to window.setTimeout) sets a timer which executes a function or specified piece of code once after the timer expires.

$(function() {
  let colors = ['red', 'blue', 'green']

  let x = 0;
  let interval = 6000;
  
  var intvl = setInterval(function(){
      $('body').css('background-color', colors[x]);
      setTimeout(function(){
      backtoWhite();
      }, interval/2);
      x++;
      if(x>=3){
        clearInterval(intvl);
      }
    }, interval);

  function backtoWhite() {
      $('body').css('background-color', 'white');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 1

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33933

Using one interval, the color change, cycling the color array can be done like this.
There is a white color applied in between each color change.

$(function() {
  let colors = ['red', 'blue', 'green']
  let index = 0;
  let whiteInBetween = false;  // A "flag" to toggle at each iteration to determine if to apply white instead of color.

  setInterval(function() {
    if(whiteInBetween){
      $('body').css('background-color', "white");
    }else{
      $('body').css('background-color', colors[index]);
      index++
    }
    whiteInBetween = !whiteInBetween;  // "Flag" toggling
    index = index%colors.length;  // Keeping the color index in range, using the remainder of the index divided by the color array length
    
  },1000);  // Interval setted faster for this demo...  

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body></body>

Upvotes: 0

Baboo
Baboo

Reputation: 4268

Based on your code structure, you can achieve what you want this way:

$(function() {
  let colors = ['red', 'blue', 'green']

  const nbColors = colors.length;
  let repetition = 3;
  let interval = 6000;

  for (let loop = 0 ; loop < repetition ; loop++) {
      for (let i = 0; i < nbColors; i++) {
        setTimeout(function() {
          $('body').css('background-color', colors[i]);
          backtoWhite();

        }, (i + loop * nbColors) * interval)
      }
  }

  function backtoWhite() {
    setTimeout(function() {
      $('body').css('background-color', 'white');
    }, interval / 2);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

But this is missing the great potential of functional programming. You should consider using callbacks to trigger the next color change once the current has finished instead of triggering all at once with different delay in execution.

Upvotes: 0

Related Questions