📜 ⬆️ ⬇️

How JavaScript Timers Work

It is extremely important to understand how JavaScript timers work. Often their behavior does not coincide with our intuitive perception of multithreading, and this is due to the fact that in reality they are performed in a single thread. Let's look at four functions with which we can control timers:
The main idea to consider is that the accuracy of the timer delay period is not guaranteed. To begin with, the browser executes all asynchronous JavaScript events in a single thread (such as a mouse click or timers) and only at the time when the time of this event arrived. This is best illustrated by the following diagram:



In this picture, there is quite a lot of information that needs to be learned, but an understanding of this will give you a deeper understanding of how asynchronous JavaScript executes. this chart shows the time vertically in milliseconds; the blue blocks show blocks of JavaScript code that has been executed. For example, the first block is executed on average within 18 ms, a mouse click blocks execution for about 11 ms, and so on
')
JavaScript can execute only one portion of code (due to the single-threaded nature of execution), each blocking the execution of other asynchronous events. This means that when an asynchronous event occurs (such as a mouse click, a timer call, or an XMLHttp request completion), it is added to the queue and executed later (the implementation, of course, varies depending on the browser, but let's call it a “queue”) .

To begin with, imagine that inside the JavaScript block, two timers start: setTimeout with a delay of 10ms and setInterval with the same delay. Depending on when the timer starts, it will work at the moment when we have not completed the first block of code. Note, however, that it does not work right away (this is not possible due to single-threaded). Instead, the deferred function enters the queue and is executed at the next available moment.

Also, during the execution of the first JavaScript block, a mouse click occurs. The handler of this asynchronous event (and it is asynchronous, because we cannot predict it) cannot be executed directly at this moment, so it also enters the queue, as does the timer.

After the first block of JavaScript code has been executed, the browser asks “What is waiting for execution?”. In this case, the mouse click handler and the timer are pending. The browser selects one of them (click handler) and executes it. The timer will wait for the next available portion of time in the queue for execution.

Note that while the mouse click handler is executed, the first interval-callback is triggered. Like the timer callback, it will be queued. However, keep in mind that when the interval works again (while the call-callback is running), it will be removed from the queue. If all the interval-callbacks were in the queue while a large piece of code was being executed, this would have resulted in a bunch of functions waiting to be called without periods of delays between the end of their execution. Instead, browsers tend to wait until there is a single function in the queue before adding another one to the queue.

Thus, we can observe the case when the third interval-callback operation coincides with the moment when it is already executed. This illustrates an important feature: the intervals do not care about what is being performed at the moment, they will be added to the queue without taking into account the delay period between performances.

Finally, after the second interval-callback is completed, we will see that there is nothing left that the JavaScript engine should do. This means that the browser is waiting for new asynchronous events to appear again. This will happen at 50ms where interval-callback will work again. At this point there will be nothing that would block it, so it will work immediately.

Let's look at an example that illustrates well the difference between setTimeout and setInterval.
setTimeout(function(){ /* Some long block of code... */ setTimeout(arguments.callee, 10); }, 10); setInterval(function(){ /* Some long block of code... */ }, 10); 

These two options are equivalent at first glance, but in reality it is not. Code using setTimeout will always have a delay of at least 10ms after the previous call (it may be longer, but never less), while code using setInterval will tend to be called every 10ms regardless of when the previous call worked.

Let's summarize all of the above:
- JavaScript engines use a single-threaded environment, converting asynchronous events into a queue waiting to be executed,
- The functions setTimeout and setInterval are fundamentally differently executed in asynchronous code,
- If the timer cannot be executed at the moment, it will be delayed until the next execution point (which will be longer than the desired delay),
- Intervals (setInterval) can be executed one after another without delay if their execution takes longer than the specified delay.

All this is extremely important development information. Knowing how the JavaScript engine works, especially with a large number of asynchronous events (which often happens), lays an excellent foundation for building advanced applications.

Source: https://habr.com/ru/post/138062/


All Articles