JavaScript timer and execution mechanism parsing

Source: Internet
Author: User

From the JS execution mechanism.

The mechanism by which the browser (or JS engine) executes JS is based on the event loop.

Since JS is a single thread, you can only perform one task at a time, other tasks will have to be queued, and subsequent tasks must wait until the previous task finishes before they can begin execution.

To avoid the meaningless wait caused by some long-running tasks, JS introduces the concept of async and uses another thread to manage asynchronous tasks.

The synchronization task executes sequentially in the main thread queue, and the asynchronous task enters another task queue without blocking the main thread. When the main thread queue is empty (execution is done), it will go to the asynchronous queue query whether there are executable asynchronous tasks (asynchronous tasks usually go into the asynchronous queue after some conditions to perform, such as AJAX requests, file read and write), if an asynchronous task can be executed to join the main thread queue to this cycle.

JS Timer

JS's timer currently has three: SetTimeout, SetInterval and Setimmediate.

The timer is also an asynchronous task, usually the browser has a separate timer module, timer delay time is managed by the timer module, when a timer into the executable state, it will be added to the main thread queue.

JS Timer is very practical, do animation is definitely used, is also one of the most commonly used asynchronous model.

Sometimes some weird problems, plus a settimeout (FN, 0) (The following shorthand settimeout (0)) solved. However, if the timer itself is unfamiliar, there will be some weird problems.

SetTimeout

SetTimeout (FN, x) indicates that the FN is executed after a delay of x milliseconds.

Use the time do not believe too much to expect, the delay time is strictly always greater than x milliseconds, as to how much depends on the implementation of JS at that time.

In addition, if multiple timers are not cleaned (cleartimeout) in time, there will be interference, which makes the delay time more elusive. So, whether or not the timer is finished, it is a good habit to clear the timers that have not been needed in time.

The HTML5 specification specifies that the minimum delay time cannot be less than 4ms, that is, if X is less than 4, it is treated as 4来. However, different browsers do not have the same implementation, for example, Chrome can set 1ms,ie11/edge is 4ms.

SetTimeout registered function FN will be given to the browser's timer module to manage, delay time to the main process execution queue, if there is no execution of the queue before the code, it will take a little time to execute to the FN, so the actual delay will be longer than the set. If there is a super-big loop before FN, the delay time is not a little bit.

(function testsettimeout() {

Const Label = ' setTimeout ';

console. Time(label);

setTimeout(() = {

console. Timeend(label);

}, ( ten);

for(let i = 0; I < 100000000; I+ +) {}

})();

The result: settimeout:335.187ms, far more than 10ms.

SetInterval

The implementation mechanism of setinterval is similar to that of settimeout, except that SetInterval is executed repeatedly.

For SetInterval (FN, 100) It is easy to create a misunderstanding: not the last time the FN was executed, the next FN will start after 100ms. In fact, setinterval and regardless of the last FN execution results, but every 100ms will put the FN into the main thread queue, and two times between the specific interval between FN is not necessarily, and settimeout actual delay time is similar, and JS implementation of the situation.

(function testsetinterval() {

let i = 0;

Const start = Date. Now();

Const Timer = setinterval(() = {

I + = 1;

I = = = 5 && clearinterval(timer);

console. Log(' ${i} times start ', Date. Now() - start);

for(let i = 0; I < 100000000; I+ +) {}

console. Log(' ${i} times end ', Date. Now() - start);

}, + );

})();

Output

1th Time Start 100

1th Time End 1089

2nd time Start 1091

2nd time End 1396

3rd time Start 1396

3rd time End 1701

4th time Start 1701

4th Time End 2004

5th time Start 2004

5th Time End 2307

Visible, although each time the FN execution time is very long, but the next time is not waiting for the last time after the execution of another 100ms to start executing, in fact, already waiting in the queue.

It can also be seen that when SetInterval's callback function execution time exceeds the delay time, it is completely invisible that there is a time interval.

If both settimeout and setinterval are executed after the delay of 100ms, then the callback function is executed first.

Setimmediate

This is a relatively new timer, currently Ie11/edge support, NODEJS support, Chrome is not supported, other browsers are not tested.

From the API name it is easy to think of settimeout (0), but Setimmediate should be considered as an alternative to settimeout (0).

In Ie11/edge, the setimmediate delay can be within 1ms, while SetTimeout has a minimum 4ms delay, so setimmediate executes the callback function earlier than settimeout (0). However, in Nodejs, it is possible for both to execute first, because the Nodejs event loop and the browser are slightly different.

(function testsetimmediate() {

Const Label = ' setimmediate ';

console. Time(label);

setimmediate(() = {

console. Timeend(label);

});

})();

Edge output: setimmediate:0.555 ms

Obviously, Setimmediate is designed to ensure that the code is executed in the next event loop, and that the unreliable way of settimeout (0) can be discarded before.

Other common asynchronous models

Requestanimationframe

Requestanimationframe is not a timer, but very similar to settimeout, in the absence of Requestanimationframe browser is generally used settimeout simulation.

Requestanimationframe is synchronized with the screen refresh, most of the screen refresh rate is 60Hz, The corresponding Requestanimationframe is triggered approximately every 16.7ms, and if the screen refreshes more frequently, requestanimationframe will trigger faster. Based on this, it is obviously unwise to use settimeout to animate browsers that support Requestanimationframe.

In browsers that do not support requestanimationframe, the best delay time is 16.7ms if you use Settimeout/setinterval to animate. If it is too small, it is likely that the DOM is refreshed twice or more times in a row, so that the frame is dropped, the animation will be stuck, and if it is too large, it will feel like a lag.

Interestingly, the first time the requestanimationframe was triggered in different browsers, the edge, about 16.7ms after the trigger, and chrome immediately triggered, similar to setimmediate. The realization of edge is supposed to be more logical.

Edge output: requestanimationframe:16.66 ms

Chrome Output: requestanimationframe:0.698ms

But the interval of two adjacent requestanimationframe is approximately 16.7ms, which is consistent. Of course, is not absolute, if the page itself performance is relatively low, the time between may become larger, which means that the page does not reach 60fps.

Promise

Promise is a very common asynchronous model, and if we want the code to be executed in the next event loop, you can choose to use settimeout (0), Setimmediate, Requestanimationframe (Chrome), and promise.

And promise's latency is lower than setimmediate, which means that promise is executed first than setimmediate.

function testsetimmediate() {

Const Label = ' setimmediate ';

console. Time(label);

setimmediate(() = {

console. Timeend(label);

});

}

function testpromise() {

Const Label = ' Promise ';

console. Time(label);

new Promise((resolve, reject) = {

resolve();

}). Then () = {

console. Timeend(label);

});

}

Testsetimmediate();

Testpromise();

Edge output: promise:0.33 ms setimmediate:1.66 ms

Although Setimmediate's callback function is registered before promise, it is promise executed first.

To be sure, in each JS environment, promise are the first to execute, setTimeout (0), setimmediate and Requestanimationframe order is uncertain.

Process.nexttick

Process.nexttick is a Nodejs API that executes earlier than promise.

In fact Process.nexttick is not going into an asynchronous queue, but rather a task that is strongly plugged into the main thread queue, although it does not block the main thread, but it blocks the execution of the asynchronous task, and if there is nested Process.nexttick, the asynchronous task will never be able to be executed.

Use caution when using setimmediate or promise, unless your code is explicitly executed before the end of the event cycle.

JavaScript timer and execution mechanism parsing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.