The process that the JS engine executes

Source: Internet
Author: User
Tags setinterval
Overview

JS engine execution process is divided into three stages, respectively, is the syntax analysis, precompilation and implementation phase, the previous article we introduced the grammar analysis and precompilation phase, then we do a simple summary, as follows:

Syntax Analysis: the completion of the loading of the code block for the syntax test, the syntax is correct to enter the precompiled phase, not correct to stop the execution of the code block, look for the next block of code and load, load completed again into the code block parsing phase

Precompilation: After the parsing phase, into the precompilation phase, create the Variable object (create the Arguments object (under the operating environment), the function declaration resolves in advance, the variable declaration is promoted), and the scope chain and this point are identified.

If there is doubt to look back on the article JS engine implementation process (i).


This article mainly analyzes the third stage of JS engine implementation-the implementation phase, before the analysis we first consider the following two questions:

JS is single-threaded, in order to avoid code parsing blocking using asynchronous execution, then its asynchronous execution mechanism is what.

Through the event loop, we understand the principle of the event loop to understand the asynchronous execution mechanism of JS, this article mainly introduces.

JS is single-threaded, then whether or not to participate in the JS execution process is only one thread.

No, there will be four threads involved in the process, but always only JS engine thread in the execution of the JS script, the other three threads only assistance, not participate in code parsing and execution. The threads participating in the JS execution process are:

JS engine thread: Also known as the JS kernel, is responsible for parsing the execution of JavaScript script program main thread (such as V8 engine)

Event-Triggering thread: A browser kernel process that is not controlled by the JS engine thread. Mainly used to control events (such as mouse, keyboard and other events), when the event is triggered, the event trigger thread will be the event to push the processing function of the event queue, waiting for the JS engine thread execution

Timer trigger Thread: The main control timer setinterval and delay settimeout, used for timer timer, timed to meet the trigger conditions of the timer, the timer processing function to promote the event queue, waiting for the JS engine thread execution.
Note: In the HTML standard, the settimeout is defined as 4ms at a time interval below 4ms.

HTTP asynchronous request thread: After a XMLHttpRequest connection, a new thread in the browser to monitor the readystate state change, if the state's callback function is set, the processing function of the state is pushed into the event queue, waiting for the JS engine thread to execute.
Note: The number of concurrent connections requested by the browser is limited, the number of Chrome and Firefox limits is 6, and IE8 is 10.

Summary: Always only JS engine thread in the implementation of the JS script, the other three threads are only responsible for the trigger conditions will satisfy the processing function of the event queue, waiting for the JS engine thread execution. implementation Phase

Let's first analyze a typical example (from tasks, microtasks, queues and schedules, recommend English based reading, very good articles):

Console.log (' script start ');

settimeout (function () {
Console.log (' settimeout ');
}, 0);

Promise.resolve (). Then (function () {
Console.log (' promise1 ');
}). Then (function () {
Console.log (' Promise2 ');
});

Console.log (' script end ');

Here I directly divide the example code structure, the simple description analysis execution process, temporarily does not explain this process the concept and the principle, the concept and the principle will explain below concretely:

Macro Task (Macro-task), macro tasks are divided into synchronization tasks and asynchronous tasks in order of execution

Synchronizing tasks

Console.log (' script start ');

Console.log (' script end ');

Asynchronous tasks

settimeout (function () {
Console.log (' settimeout ');
}, 0);

Micro Task (Micro-task)


Promise.resolve (). Then (function () {
Console.log (' promise1 ');
}). Then (function () {
Console.log (' Promise2 ');
});

In the JS engine execution, after entering the execution phase, the code is executed in the following order:

Macro Task (sync Task)--> Micro Task--> Macro task (asynchronous Task)

The output results are:

Script Start
Script End
Promise1
Promise2
SetTimeout

into the ES6 or node environment, JS tasks are divided into two kinds, namely, macro Task (Macro-task) and micro-task (Micro-task), in the latest ECMAScript, micro-task called jobs, macro tasks called task, their execution order as above. Perhaps a lot of people do not understand the above analysis, then we continue to the above examples of detailed analysis. macro Tasks

Macro Tasks (Macro-task) can be divided into synchronization tasks and asynchronous tasks:

Synchronization tasks are tasks that are executed sequentially on the main thread of the JS engine, and only after the previous task has been executed can the latter be executed to form an execution stack (function call stack).

Asynchronous task refers to not directly into the JS engine main thread, but to meet the trigger conditions, the relevant thread will the asynchronous task to push the task Queue (task queue), waiting for the JS engine main thread of the task execution completed, idle read the tasks performed, such as asynchronous Ajax,dom events, SetTimeout and so on.

Understanding the order in which synchronization tasks and asynchronous tasks are performed in macro tasks is equivalent to understanding the JS asynchronous execution mechanism-the event loop. Event Loops

The event loop can be understood to consist of three parts, namely:

Main thread Execution stack

Asynchronous task Wait Trigger

Task queues

Task queue is the data structure of the queue to manage the event task, characterized by advanced first out, backward after.


Here is a direct reference to a famous picture (refer to the speech from Philip Roberts, "Help, I ' M. Stuck in a Event-loop"), which helps us understand the following:

In the JS engine main thread execution process:

First, perform the synchronization task of the macro task, form an execution stack on the main thread, which can be understood as the function call stack;

When functions in the execution stack are called to some asynchronous execution APIs (such as asynchronous Ajax,dom events, SetTimeout APIs), the corresponding threads (HTTP asynchronous request thread, event trigger thread and timer trigger thread) are opened for monitoring and control

When an event for an asynchronous task satisfies the trigger condition, the corresponding thread pushes the handler function of the event forward in the task queue, waiting for the main thread to read the execution

When the tasks on the main thread of the JS engine are completed, the events in the task queue are read, the event tasks in the task queue are pushed in the main thread, and the task queues are executed

When the task on the main thread of the JS engine is finished, the event task in the task queue is read again, so the loop, which is the process of the event loop

If it is still not understood, then we again take the above example for detailed analysis, the example of the macro task in the Code section is:

Console.log (' script start ');

settimeout (function () {
Console.log (' settimeout ');
}, 0);

Console.log (' script end ');

The code execution process is as follows:

The JS engine main thread executes in code order, when executes to Console.log (' script start '), the JS engine main thread thinks that the task is the synchronization task, so immediately executes the output script start, then continues to execute downward;

JS engine main thread execution to settimeout (function () {console.log (' settimeout ');}, 0), JS engine main thread think settimeout is asynchronous task API, The browser kernel process is requested to open the timer thread to timing and control the settimeout task. Since the settimeout is defined as 4ms in the HTML standard, the timer thread pushes the callback processing function forward in the task queue to wait for the main thread to execute, and then the JS engine main thread continues to execute downward when the time elapses to 4ms.

The JS engine main thread executes to the Console.log (' Script End '), the JS engine main thread thinks the task is the synchronization task, so immediately executes the output script

JS engine on the main thread after the completion of the task (output script start and script end), the main thread is idle, then start reading the Task Queue event task, the task team in the event task to promote the main thread, according to the task queue sequence execution, the final output settimeout, So the output order is the script start script end settimeout

The above is the JS engine to perform the macro task of the entire process.

After understanding the process, we do some extended thinking:

We all know that settimeout and setinterval are timers for asynchronous tasks that need to be added to the task queue to wait for the main thread to execute, and then using the settimeout simulation to implement SetInterval will make a difference.

The answer is different, we might as well think about it:

SetTimeout implementation SetInterval can only be called recursively by recursion

SetTimeout the event to the task queue at the specified time, and only after the SetTimeout event in the task queue is executed by the main thread will it continue to push the event to the task queue at the specified time. Then the SetTimeout event execution must be longer than the specified time, the exact difference is related to the code execution time

SetInterval pushes an event to the task queue every time that it is accurate, regardless of whether the last SetInterval event has been executed, so there is a possibility of setinterval event tasks accumulating, Causes setinterval code to repeatedly execute repeatedly, affecting page performance.

Combined with the above analysis, using settimeout to realize the timing function is better than setinterval performance. Of course, if you do not need to be compatible with the lower version of IE browser, using Requestanimationframe is a better choice.

We continue to think further, as follows:

High frequency triggered events (such as scrolling events) triggered too high frequency will affect the performance of the page, or even the page cotton, we can use the principle of the timer to optimize it.

Is possible, we can use settimeout to implement the principle of the timer, the High-frequency trigger event optimization, the realization point is to combine multiple triggering events into one, this is the stabilization and throttling, this article does not do a specific explanation, we can study, have the opportunity to open another article analysis. Micro-Task

Micro-tasks are a type of task that occurs in ES6 and node environments, and if you do not consider the ES6 and node environments, we need to understand that the execution of the macro task event loop is sufficient, but in the ES6 and node environments, we need to understand the order in which the micro tasks are executed.
Micro-Task (Micro-task) API mainly includes: Promise, Process.nexttick

Here we refer directly to a flowchart to help us understand the following:

There are two types of tasks that you perform in a macro task. are synchronous and asynchronous tasks, because asynchronous tasks advance task queues when they meet trigger conditions, then wait for tasks on the main thread to finish, read task events in the task queue, and finally push the main thread to execute. So here is the asynchronous task, the task queue, as a new macro task. The procedure is executed as shown in the previous illustration:

Perform the synchronization task in the macro task and finish the execution;

Check for the existence of executable micro-tasks, some words to perform all micro-tasks, and then read the Task Queue task events, to promote the main thread to form a new macro task; If not, read Task Queue task events, push the main thread to form a new macro task

Perform the event tasks for the new macro task, and then check for the existence of an executable micro-task, so that repeated loops

This is the detailed event loop after adding a micro-task, and if not, then make a comprehensive analysis of the first example, as follows:

Console.log (' script start ');

settimeout (function () {
Console.log (' settimeout ');
}, 0);

Promise.resolve (). Then (function () {
Console.log (' promise1 ');
}). Then (function () {
Console.log (' Promise2 ');
});

Console.log (' script end ');

The implementation process is as follows:

code block through parsing and precompiled, into the implementation phase, when the JS engine main thread execution to Console.log (' script start '), the JS engine main thread that the task is synchronous task, so immediately execute output script start, and then continue to execute downward;

JS engine main thread execution to settimeout (function () {console.log (' settimeout ');}, 0), JS engine main thread think settimeout is asynchronous task API, The browser kernel process is requested to open the timer thread to timing and control the settimeout task. Since the settimeout is defined as 4ms in the HTML standard, the timer thread pushes the callback processing function forward in the task queue to wait for the main thread to execute, and then the JS engine main thread continues to execute downward when the time elapses to 4ms.

JS engine main thread execution to Promise.resolve (). Then (function () {console.log (' promise1 ');}). Then (function () {console.log (' promise2 ');), the JS engine main thread thinks that promise is a micro-task, which divides the task into micro-tasks and waits for execution

The JS engine main thread executes to the Console.log (' Script End '), the JS engine main thread thinks the task is the synchronization task, so immediately executes the output script

The macro task on the main thread completes, then starts to detect whether there is an executable micro-task, detects a promise micro-task, then executes immediately, outputs Promise1 and PROMISE2

When the micro-task is finished, the main thread begins to read the event task settimeout in the task queue, pushes the main thread into the new macro task, executes it in the main thread, and outputs the settimeout

The final output result is:

Script Start
Script End
Promise1
Promise2
SetTimeout

Summary

Above is the JS engine to perform all the process, JS engine implementation process is not complex, as long as more than thinking more research can be understood, understand the process can be to a certain extent to improve the understanding of JS.

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.