JavaScript’s setInterval() and setTimeout() functions allows us to execute JavaScript code at specific time intervals. In most cases the timer and your code works intuitively. The single thread and other language behaviour protects most JavaScript developers. Nevertheless it is very important to understand the fundamentals of JavaScript timers.
Using setInterval and setTimeout
Let’ start by showing how to use these functions. There are two ways of setting up a timer:
var timerId = setTimeout(fnCallback, delayInMilliseconds);
This will call the callback function once after an delay in milliseconds.
var timerId = setInterval(fnCallback, intervalInMilliseconds);
And this will call the callback function continously every given interval time span.
To stop a timer use the function clearInterval() with a timer id. Like
clearInterval(timerId);
Timer Accuracy and the Event Queue
There is no guarantee that the fnCallback function is called at a specific timer delay. This is based on the single thread execution and the concept of the event queue. Single thread means that JavaScript can only execute one piece of a code at a time. Every event, like a simple mouse click or more complex like drawing the page, seams to be asynchronous, but they are all organized within the event queue.
To make it clearer the following diagram demonstrates it.

Every piece of code (function) is put into the queue. If one block of code needs more time to execute, then everything else will be delayed. The above figures shows an example of it. @0 a interval is initialized. Let’s assume that the code is still ongoing and a mouse event occours @200. @300 the code execution is completed. The next one will be the code for the mouse event, because it was placed to the queue earlier then the interval code. In the end the interval code execution startet @400 with a 100ms delay.
So never rely on exact timing behaviour. If we are planning to do some animations or a game then we have to measure the time between two interval codes to calculate a correction coefficient for ourwork. For more about game loops take a look at this article “The Game Loop”.
What happens if the callback function takes longer?
Longer than the interval time. For example we have a interval time of 100ms, but the code execution needs 200ms. @100 the first interval code is starting. @200 the next interval wants to run, but it is queued in and waiting. (remember single thread). @300 there can happen different things: the second interval code can be started or another code, like an event handler, will be executed. So again, there is no guaranty that the second interval code is starting @300. What about a third interval code that should start @300? This one is not queued in. The event queue contains only one active/running interval code and one waiting.

So the event queue will not be flooded. Nevertheless try to avoid such situations, it can block UI event handling and other code parts.
Use Timers to Perform Non Blocking Operations
The first figure shows an event queue with a code block that takes some time. Imagine this code is doing some complex calculation and will take a while. During this time no other code can be executed (single thread), this means for example that the application user interface can not be responsive to users.
To break up a blocking code we can split it in different fragments and add some delay between their execution. This example demonstrate a split into 10 parts and uses a setTimeout of 20ms.
var fragments = 10;
var currentFragment = 0;
function doSomething()
{
// Insert calculation here
currentFragment++;
if (currentFragment < fragments)
{
setTimeout(doSomething, 20);
}
}
setTimeout(doSomething, 20);
This above example ensures that there is at least a 20ms time slot to execute other code like event handling.

The figure shows us, how it can look like on the event queue. On the left side the blocking code and on the right side the fragmented version. And again be aware that the 20ms is not guaranteed and a longer mouse click event handling can change it.
Look at http://jsfiddle.net/tntg6/3/ for a full working demo calculating Fibonacci numbers.
To truly run code in background use web workers, they are also able to utilize multi-core CPU’s and run code on another core. Web workers are only available for modern (HTML5) browsers.
Time and Timer Resolution
To complete the picture about time and timers in JavaScript we have to look at the accuracy. The accuracy is different between getting the time with Date() and using setTimeout(…) or setInterval(…).
Windows machines have a timer resolution of 10-15.6ms by default. Until recently, all browsers used the system timer, so they all were stuck to this resolution. On other OS, like OSX the system timer has a much higher resolution. Now a days, actual browsers have a much better resolution of 1ms. This just relates to the Date().
For timers actual browsers on desktop commonly using a 4ms resolution. But again it is not guaranteed. On older webkit browser you will get a 10ms resolution.
The resolution can change, depending on various circumstances. Some browser change the resolution for inactive tabs to 1000ms (Firefox, Chrome, …). Addionally chrome handles minimized tabs as inactive. The HTML5 specs leaves a lot of room for timer resolution and changing it during runtime. For more on this topic, read Nicolas C. Zakas great article about “Timer resolution in browsers”.
Recap
- Code execution at specified time is not guaranteed
- Single Thread JavaScript execution organized via event queue
- Long code execution can block the user interface
- Different time resolutions. (In general: 1ms for Date, 4ms for Timers, 1000ms for inactive)
References
[1] Supercharged JavaScript Graphic, Raffaele Cecco, O’Reilly, p. 38-45
[2] How JavaScript Timers Work, John Resig, http://ejohn.org/blog/how-javascript-timers-work/
[3] Timer resolution in browsers, Nicholas C. Zakas, http://www.nczonline.net/blog/2011/12/14/timer-resolution-in-browsers/
[4] Timers in HTML5, http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers
Comments
Hi. Great post! I am a bit confused about the proposed solution for breaking up blocking code though. The way I read it the blocking code calculation in doSomething() would run (repeat itself) 10x, from the beginning, and not break itself up into chunks as your diagram suggests. Am I missing something? Thanks, and maybe you can post a jsfiddle to demo?
I think what you are missing is the splitting of the “real” work in doSomething. How this shall work has to be done individually for your specific work.
This full demo calculates some fibonacci numbers: http://jsfiddle.net/tntg6/1/
In this example I used a 1000ms timeout for a good effect.
The break up in junks for a non blocking purpose also works with 0ms timeout.
Update:
Fixed a bug in the example code for non blocking code with setTimeout.
Got it! Great example on jsfiddle. Thanks again for posting this.
There is no reason to have a 20ms timeout in a long-running function. 1ms is more than enough time for an event handleer to get in there. The only reason I don’t say 0ms is because in some JS engines (though no browser engines AFAIK), a 0ms timeout still blocks.
Setting a timeout to 20ms just wastes time and makes your code take longer to run.
The most efficient way to access the system timer is to simply use the VCL TTimer component. TTimer is very simple to use. Just drop one on the form and set its Interval property to the timer interval you wish to use. The Interval property is specified in milliseconds. To create a timer that fires each second, for example, set the Interval property to 1000. Next create an event handler for the OnTimer event. Place code in the event handler that you wish to execute each time the timer fires. The timer can be enabled or disabled by setting the Active property to either true or false.
@Mark Thanks for your comment. I agree with you. The 20ms timeout was used just as an example. I will edit the post to make it clear.
The 0ms blocking issue is new to me. Can you give me any source?
For “modern” Browser, according to the living HTML5 spec, a minimum value of 4ms shall be used. So 0ms or 1ms will be changed to 4ms.
http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers