Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the reason JavaScript setTimeout is so inaccurate?

I got this code over here:

var date = new Date(); setTimeout(function(e) {     var currentDate = new Date();     if(currentDate - date >= 1000) {          console.log(currentDate, date);          console.log(currentDate-date);     }     else {        console.log("It was less than a second!");        console.log(currentDate-date);     } }, 1000); 

In my computer, it always executes correctly, with 1000 in the console output. Interestedly in other computer, the same code, the timeout callback starts in less than a second and the difference of currentDate - date is between 980 and 998.

I know the existence of libraries that solve this inaccuracy (for example, Tock).

Basically, my question is: What are the reasons because setTimeout does not fire in the given delay? Could it be the computer that is too slow and the browser automatically tries to adapt to the slowness and fires the event before?

PS: Here is a screenshot of the code and the results executed in the Chrome JavaScript console:

Enter image description here

like image 388
Tomás Avatar asked Jan 13 '14 17:01

Tomás


People also ask

Why JavaScript timer is unreliable?

Even more concerning is the fact that it resumes from the same time it paused on, missing the time period in between. So, if we create any mission critical application in Javascript which uses timer, the result would be catastrophic. The reason why this happens is because Javascript is single threaded.

Is setTimeout reliable?

No, you can't be absolutely certain of anything, and javascript timers aren't very accurate either, but most of the time they are accurate enough, and will execute the function close enough to the set time.

What is the alternative for setTimeout in JavaScript?

The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) All arguments have the same meaning. But unlike setTimeout it runs the function not only once, but regularly after the given interval of time.

Why is setTimeout a security issue?

It could become a serious risk if we allowed user input or query params to be passed directly as the function callback. A malicious actor could inject code that way, which our application would evaluate.


1 Answers

It's not supposed to be particularly accurate. There are a number of factors limiting how soon the browser can execute the code; quoting from MDN:

In addition to "clamping", the timeout can also fire later when the page (or the OS/browser itself) is busy with other tasks.

In other words, the way that setTimeout is usually implemented, it is just meant to execute after a given delay, and once the browser's thread is free to execute it.

However, different browsers may implement it in different ways. Here are some tests I did:

var date = new Date(); setTimeout(function(e) {     var currentDate = new Date();     console.log(currentDate-date); }, 1000);  // Browser Test1 Test2 Test3 Test4 // Chrome    998  1014   998   998 // Firefox  1000  1001  1047  1000 // IE 11    1006  1013  1007  1005 

Perhaps the < 1000 times from Chrome could be attributed to inaccuracy in the Date type, or perhaps it could be that Chrome uses a different strategy for deciding when to execute the code—maybe it's trying to fit it into the a nearest time slot, even if the timeout delay hasn't completed yet.

In short, you shouldn't use setTimeout if you expect reliable, consistent, millisecond-scale timing.

like image 81
p.s.w.g Avatar answered Oct 12 '22 12:10

p.s.w.g