1

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

2 Answers2

1

I believe the only way of doing such thing, is to declare the setTimeouts inside each other,something like:

setTimeout(function(){
    //execute the work to be done
    setTimeout(function(){
        //execute the work to be done
        // ... and so on
    })
});

You can try to rearrange your code logic to do something like this. If in the meantime I find a better solution, I'll edit the answer.

EDIT: This answer explains pretty well how the setTimeouts execution is handled.

EDIT 2: This is a bad approach since removing dynamism of the code is not a good practice. Check the answer from @epascarello

Community
  • 1
  • 1
Bruno Santos
  • 154
  • 1
  • 8
1

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>
epascarello
  • 204,599
  • 20
  • 195
  • 236