Ensure Execution Order Of Multiple SetTimeout() Functions In JavaScript

masterjosh
by
masterjosh
Apr 04, 2019
Ensure Execution Order Of Multiple SetTimeout() Functions In JavaScript

Consider the following piece of JavaScript code:


setTimeout(function() {
  console.log("one");
}, 1000);
setTimeout(function() {
  console.log("two");
}, 1000);

Looks pretty straightforward. We would expect the text “one” and “two” to be printed out to the console in order. This should happen after a 1 second delay as defined by the variable value of 1000 that has been set for each setTimeout() function.

That “1000” actually means 1000 milliseconds (or 1 second) and we can vary the value however we want.

The Multiple SetTimeout Problem

The problem with multiple setTimeout functions like the above is that even if we may often get “one two” printed out to the console in the correct order, we cannot rely on this behavior. Delays due to CPU load, other tasks, etc can cause the timer schedule/order to be incorrect or unexpected sometimes.

While it is true that JavaScript executes in a single thread, when it comes to timer schedules like this, the single-threaded behavior of JavaScript is not enough to guarantee our desired timer execution order.

So instead of “one two”, the output to the console may sometimes be “two one”.

This problem becomes more obvious when the above piece of code is tested across different browsers and browser states. For example, when the window is minimized and then maximized in Chrome, timeouts defined in events that come from external sources (e.g. webworkers or websockets) may be executed in the wrong order.

In the code snippet above, we used the same delay of 1 second (1000ms) for both setTimeout functions. But in practice, you may want different values for your delays. You may also be working with more than just 2 delays and your algorithm may depend on their correct execution order.

Solution: Nested SetTimeouts

To solve this problem, code your timeouts in a nested format like this:


setTimeout(function(){
    // Do the first thing
    console.log("one");
    setTimeout(function() {
        // Do a second thing
        console.log("two");
    }, 1000);
}, 1000);

By coding our timeouts this way, we’re effectively scheduling the next delay to start after the end of the previous delay. This will delay execution without any chance of “two” being printed before “one”.

You can add more nested delays and vary the delay times however you like and play with it across different browsers and browser states. By it’s very nested structure, this code guarantees proper execution order for your multiple setTimeout() functions.

There are probably other framework-based methods of working with multiple setTimeout functions like the above. But the implementation I have described here uses plain old JavaScript without relying on any third-party frameworks. Hope this helps someone.




Add Comment