Search code examples
javascriptloopsprogress-barsettimeoutmilliseconds

setTimeout in loop with different times


I have a loading bar that I'm creating and am passing different milliseconds and style params in var barMovement.

My issue is that in the setTimeout function the last params which has a time of 100 milliseconds is not being output last.

When I console log the results they come out as 100, 200, 200, 100, 200, 300, when it should be 100, 200, 200, 200, 300, 100.

If I understand correctly, the last param of 100 is being output first because it's faster, but is there a fix for this or a way to make setTimeout delay until the previous setTimeout loop is complete?

Thanks!

function BarSequence(style){
 this.style = style

 this.move = function(styles) {
  var i = 0;

  for(len = styles.length; i < len; i++){

    (function loopy(index) {

        setTimeout(function() {
          console.log(style[index])
        }, i * style[index][0]);
    })(i);

   }
  }
}

var barMovement = new BarSequence([
[100, { width: '10%' }],
[200, { width: '20%' }],
[200, { width: '50%' }],
[200, { width: '80%' }],
[300, { width: '90%' }],
[100, { width: '100%' }]
]);

barMovement.move(barMovement.style);

Solution

  • You are multiplying it by the index. So you timeouts are 0, 200, 400, 600, 1200, 500 so the last one is going to come before between the 400 and 600

    In order to have them load in order, you would need to append the previous time to it. What you should do is not use a loop for timeouts. Just increment a counter and go over the array.

    var barMovement = [
      [100, {width: '10%'}],
      [200, {width: '20%'}],
      [200, {width: '50%'}],
      [200, {width: '80%'}],
      [300, {width: '90%'}],
      [100, {width: '100%'}]
    ];
    
    var cnt = 0;
    
    function run() {
      window.setTimeout(function() {
        document.getElementById("bar").style.width = barMovement[cnt][1].width
        cnt++;
        if (cnt < barMovement.length) run();
      }, barMovement[cnt][0])
    }
    
    run()
    #bar {
      background-color: green;
      width: 0;
    }
    <div id="bar">&nbsp;</div>