Skip to content Skip to sidebar Skip to footer

Random Behavior Of Settimeout On Console. How To Get Counts In Order And Reason For This Behavior?

for (var i = 0; i < 5; i++) { function timer(j) { setTimeout(function() { alert(j); }, 1000); } timer(i); }; This code is generating random outcomes of coun

Solution 1:

When the script runs, the for loop is running, and you are initializing 5 setTimeouts all at once, each of which times out after 1000 milliseconds. Because they're all set to run at the same time, and since setTimeout isn't even millisecond-precise, the timeout order won't be predictable. Another potential confounding factor is that alertblocks.

As the comments below illustrate, the setTimeouts may happen to run in the order they were set, but it's not guaranteed - behavior may differ across browsers. So, if you want to make sure they run in the order they were set, add a few milliseconds for each iteration:

for (var i = 0; i < 5; i++) {
  functiontimer(j) {
    setTimeout(function() {
      console.log(j);
    }, 1000 + (j * 12));
  }
  timer(i);
}

alert version:

for (var i = 0; i < 5; i++) {
  functiontimer(j) {
    setTimeout(function() {
      alert(j);
    }, 1000 + (j * 12));
  }
  timer(i);
}

Solution 2:

You're starting five timers, in very quick succession, and all with the same delay. I suspect that if you looked at the internal details of when the timers are intended to fire, they'd all have the exact same target time, unless the system clock happens to "tick" between timer instantiations.

There's no strict ordering of timers that are meant to fire at effectively the same time. All you're seeing is several timers firing at roughly the same time, in no particular order. It's like setting off 5 fireworks at the same time, each with the same fuse length - they'll all go off at "about" the same time, but there's no guarantee that the one you lit first will ignite first. This is just the nature of timers, and it's best not to fight it.

If you want to do lots of things all at the same time in the future, I suggest you start a single timer that executes all the desired operations when it fires.

If you really, really need additional ordering but for everything to fire at "basically the same time", you could make each timer keep a reference to the "previous" timer, and wait for that timer to finish first. It would be pretty ugly though, and I'd at least try to avoid requiring it. Either the events are meant to be independent, in which case the ordering doesn't matter, or they're interdependent, in which case you should probably be scheduling them differently.

Solution 3:

Random behavior of setTimeout on console, ...and reason for this behavior?

As mentioned already, the order of execution for each setTimeout is not guaranteed, and that is because they run independently of each other, based on a given delay and not in their initiated order, and can therefore fire randomly.

How to get counts in order...?

Again as mentioned, a minor change to the delay could be one solution, still, that is not guaranteed either, for the same reason, though with a big enough delay difference it most likely will.


Assuming you want to run an amount of functions, with a delay and in a certain "guaranteed" order, here is one solution, where one store the functions in an array, and then execute them 1-by-1.

Stack snippet - with alert

var fn_arr = [];

for (let i = 0; i < 5; i++) {
  fn_arr.push( function() { alert(i) } )  
};

setTimeout(function() {
  fn_arr.forEach( (fn) =>fn() )
}, 1000);

Stack snippet - with console

var fn_arr = [];

for (let i = 0; i < 5; i++) {
  fn_arr.push( function() { console.log(i) } )  
};

setTimeout(function() {
  fn_arr.forEach( (fn) =>fn() )
}, 1000);

Post a Comment for "Random Behavior Of Settimeout On Console. How To Get Counts In Order And Reason For This Behavior?"