Why you can't trust setTimeout

Shuvo - Dec 3 '21 - - Dev Community

setTimeout in JavaScript takes time in millisecond so it must be very accurate right?

Well not necessarily. In this article let's explore why.

We all know that JavaScript is single-threaded. Meaning that it can only calculate one thing at a time.
But now imagine you have a setTimeout that is suppose to fire after 10000ms or 10s. So now JS have to keep track of the time passed. But in between that 10s the user might do some interaction with your page. Now JavaScript have to react to them as well.

But if JavaScript is single threaded how it's gonna keep track of passed time while reacting to user activity? That would be performing multiple calculation at the same time right?
Well not really because JavaScript is not keeping track of time. In fact JavaScript doesn't natively support setTimeout even. Then how are we able to use setTimeout? Well these special asynchronous functions like setTimeout, setInterval are provided to JS by the environment it is currently running on. For example in case of Chrome JavaScript runs on the V8 engine, and Fire Fox uses SpiderMonkey as its JavaScript engine etc.

So basically when you call setTimeout, JavaScript under the hood tells its environment/the engine its running on that once all the synchronous code is done executing set a timer and once the timer reaches the given time execute the function.
Now notice that I said "once all the synchronous code is done executing". And this is where the problem lives. The timer for setTimeout won't start until all the normal synchronous codes like dom manipulations, loops etc. aren't fully executed.
And those synchronous codes might take some time to execute.
Here's a dummy code that takes couple of milliseconds to execute.

//JS hack: +new Date() will give you current time in milliseconds 😉
let currentTime = +new Date()
//Dummy long loop
for(let i = 0; i < 999999999; i++){}
//Current time after the loop is over
let endTime = +new Date()
console.log("Ran after: " + (endTime - currentTime) + "ms")
Enter fullscreen mode Exit fullscreen mode

JavaScript get code execution time
And so if we had a setTimeout out in our code that is suppose to run after lets say 50ms, it might run a few milliseconds late

let currentTime = +new Date()
setTimeout(function(){
    let endTime = +new Date()
    console.log("Ran after: " + (endTime - currentTime) + "ms")
}, 50)
for(let i = 0; i < 99999999; i++){

}
Enter fullscreen mode Exit fullscreen mode

JS setTimeout running late

Conclusion

Although setTimeout is fine to use most of the time, but for very time sensitive task it might not be the ideal choice

Make sure you checkout my other articles and YouTube channel

Was it helpful? Support me on Patreon

Patreon Logo

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .