Pay attention to “songbao write code”, selected good articles, a question of the day

Saucxs | songEagle

2020, real “rat” is not easy

In 2021, “niu” changes the world

When the wind is strong and the tide is surging, the heavy task must be bravely hoof!

Time is always your own

Every minute is also for their future matting and value-added

One, foreword

This topic covers JavaScript, Node, Vue, React, browser, HTTP, etc.

Q: What is the execution process of the JS engine?

Let’s divide this into two articles.

This part is about parsing and precompiling.

The next one is the implementation phase.

Second, the overview

Js engine execution process is mainly divided into three stages, respectively is the syntax analysis, precompilation and execution stage, the last article we introduced the syntax analysis and precompilation stage, so we first make a simple summary, as follows:

1. Grammar analysis: check the grammar of the loaded code block separately. If the syntax is correct, it enters the pre-compilation stage; If not, stop the execution of the code block, find the next code block and load it. After loading, enter the syntax analysis stage of the code block again.

Precompile: Create variable object (create arguments object (function run environment), function declaration is parsed in advance, variable declaration is promoted), scope chain and this point.

If there is doubt about grammar analysis and precompiled, : javascript engine perform understanding of grammar analysis of the process and its compilation phase (mp.weixin.qq.com/s/Lhd5N5a1b…

This paper mainly analyzes the third stage of JS engine execution – execution stage, before the analysis we first consider the following two questions:

1, JS is a single thread, in order to avoid code parsing blocking using asynchronous execution, so its asynchronous execution mechanism is what?

Answer: Through the Event Loop (Event Loop), understand the principle of the Event Loop to understand the ASYNCHRONOUS execution mechanism of JS, this paper mainly introduces.

Js is a single thread, so does that mean that there is only one thread participating in the js execution process?

A: No, there are four threads involved in this process, but only the JS engine thread is always executing the JS script. The other three threads are assisting, not parsing and executing the code. The threads involved in js execution are:

(1) JS engine thread: also known as JS kernel, which is responsible for parsing the main thread of executing Javascript scripts (such as V8 engine).

(2) Event trigger thread: it belongs to the browser kernel process and is not controlled by THE JS engine thread. It is mainly used to control events (such as mouse, keyboard and other events). When the event is triggered, the event triggering thread will push the event processing function into the event queue and wait for the JS engine thread to execute.

(3) Timer trigger thread: mainly controls timer setInterval and delay setTimeout, which are used for timer timing. When the timer is finished and trigger conditions of timer are met, the timer processing function is pushed into the event queue, waiting for JS engine thread to execute.

Note: In the HTML standard, W3C states that setTimeout below 4ms is counted as 4ms.

(4) HTTP asynchronous request thread: after connecting with XMLHttpRequest, a new thread is opened through the browser to monitor readyState state changes. If the callback function of the state is set, the processing function of the state is pushed into the event queue, waiting for the JS engine thread to execute.

Note: Browsers have a limit on the number of concurrent connections to the same domain. Chrome and Firefox have a limit of 6 connections, and Ie8 has a limit of 10 connections.

Conclusion: Only the JS engine thread is always executing the JS script, and the other three threads are only responsible for pushing the handlers that meet the trigger conditions into the event queue, waiting for the JS engine thread to execute.

Third, the implementation stage

Queues and schedules – – Queues and schedules – – – – – – – –

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');
Copy the code

Directly divide the code structure of the example, simply describe the analysis execution process;

Instead of explaining the concepts and principles involved in this process, the concepts and principles will be explained as follows:

1. Macro-task

Macro tasks are divided into synchronous tasks and asynchronous tasks according to the execution order

(1) Synchronization tasks

console.log('script start');
console.log('script end');
Copy the code

(2) Asynchronous tasks

setTimeout(function() {
  console.log('setTimeout');
}, 0);
Copy the code

2. Micro-task

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});
Copy the code

In the JS engine execution process, after entering the execution stage, the code execution sequence is as follows:

Macro Task (Synchronous task) –> Micro Task –> Macro task (asynchronous task)

Output result:

script start
script end
promise1
promise2
setTimeout
Copy the code

In ES6 or Node environment, JS tasks are divided into two types, namely macro-task and micro-task. In the latest ECMAScript, micro-task is called JOBS, and macro task is called Task, and they are executed in the above order. Many people may not understand the above analysis, so let’s continue to analyze the above example in detail.

2.1 the macro task

Macro tasks can be divided into synchronous tasks and asynchronous tasks:

1. Synchronous tasks refer to the tasks that are executed sequentially on the main thread of JS engine. Only after the execution of the previous task is completed, the latter task can be executed, forming an execution stack (function call stack).

2. Asynchronous task refers to that the asynchronous task is not directly entered into the main thread of THE JS engine, but when the trigger condition is met, the relevant thread pushes the asynchronous task into the task queue, waits for the completion of the task on the main thread of the JS engine, and reads the executed task when idle, such as asynchronous Ajax, DOM events, setTimeout, etc.

To understand the execution sequence of synchronous and asynchronous tasks in macro tasks, it is equivalent to understanding the JS asynchronous execution mechanism – Event Loop.

2.1.1 Event Loop

The event cycle can be understood as consisting of three parts:

1. Main thread execution stack

2. Asynchronous tasks wait to be triggered

3. Task queues

Task queue is the data structure of the queue to manage event tasks. It is characterized by first in, first out, last in, last out.

Here is a direct reference to a famous picture (from Philip Roberts’ talk “Help, I’m Stuck in an Event-Loop”) to Help us understand:

In the main thread execution of the JS engine:

1. Perform the synchronization task of the macro task first, forming an execution stack on the main thread, which can be understood as the function call stack.

2. When the functions in the execution stack are called to some ASYNCHRONOUS execution apis (such as asynchronous Ajax, DOM events, setTimeout, etc.), the corresponding threads (Http asynchronous request threads, event-triggered threads and timer-triggered threads) will be started for monitoring and control.

3. When the event of an asynchronous task meets the trigger condition, the corresponding thread will push the event handler to the task queue and wait for the main thread to read and execute the event.

4. When the tasks on the main thread of THE JS engine are completed, the events in the task queue will be read, and the events in the task queue will be pushed into the main thread and executed in the order of the task queue

5. When the tasks on the main thread of the JS engine are completed, the Event tasks in the task queue will be read again, and so on. This is the process of Event Loop.

If that still doesn’t make sense, let’s go through the above example again, where the code part of the macro task is:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

console.log('script end');
Copy the code

The code execution process is as follows:

1. The main thread of the JS engine is executed in code order, when executed to console.log(‘script start’); The main thread of the JS engine considers the task to be a synchronization task, so it immediately executes the output script start, and then continues down.

SetTimeout (function() {console.log(‘setTimeout’); }, 0); , the main thread of the JS engine considers setTimeout as an API of asynchronous task, so it applies to the browser kernel process to start the timer thread for timing and control of the setTimeout task. As W3C stipulated in HTML standard that setTimeout interval below 4ms is 4ms, when the timer thread reaches 4ms, the callback handler is pushed into the task queue to wait for the main thread to execute, and then the JS engine main thread continues to execute.

Console. log(‘script end’); The main thread of the JS engine considers this task to be a synchronous task, so it immediately executes the output script end.

4. After the execution of tasks on the main thread of THE JS engine is completed (outputting script start and Script end) and the main thread is idle, it starts to read the event tasks in the task queue, pushes the event tasks in the task queue into the main thread, executes them in the order of the task queue, and finally outputs setTimeout. Therefore, the output sequence is script start script end setTimeout.

This is how the JS engine performs the macro task.

Now that we understand this 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. Is there any difference between using setTimeout simulation to implement setInterval?

The answer is different, so let’s think about it:

SetInterval can only be called recursively.

2. SetTimeout is to push the event to the task queue at the specified time. Only when the setTimeout event in the task queue is executed by the main thread, it will continue to push the event to the task queue at the specified time, then the execution of the setTimeout event must be longer than the specified time. The difference depends on the code execution time.

3. SetInterval pushes an event into the task queue at precise intervals every time, regardless of whether the previous setInterval event has been executed. Therefore, it is possible to accumulate setInterval event tasks, leading to the repeated and consecutive execution of setInterval codes. Affecting page performance.

Based on the above analysis, using setTimeout to realize the timing function is better than setInterval. Of course, if you don’t need to be compatible with lower versions of Internet Explorer, using requestAnimationFrame is a better choice.

Let’s go ahead and do some further thinking, as follows:

Events triggered with high frequency (such as scrolling events) will affect page performance and even cause page lag if the triggering frequency is too high. Can we use the principle of timer to optimize?

Yes, we can use setTimeout to realize the timer principle and optimize the events triggered by high frequency. The realization point is to combine multiple triggering events into one, which is the anti-shake and throttling. This paper will not give specific explanation for the moment, you can study it by yourself, and I will write another article for analysis if possible.

2.2 the task

Microtasks are a type of task that occurs in ES6 and Node environments. Without es6 and Node environments, it is sufficient to understand the execution process of macro task event loops, but in ES6 and Node environments, it is necessary to understand the execution sequence of microtasks. The API of micro-task mainly includes Promise, process.nexttick

Here we directly quote a flow chart to help us understand, as follows:

There are two types of tasks executed in macro tasks, namely synchronous tasks and asynchronous tasks, because asynchronous tasks will not advance task queue until they meet trigger conditions, and then wait for the completion of tasks on the main thread to read the task events in the task queue, and finally advance the execution of the main thread. So the asynchronous task, the task queue, is the new macro task. The execution process is shown in the figure above:

1. Perform the synchronization task in the macro task.

2. Check whether there are executable microtasks, if there are, execute all the microtasks, and then read the task events of the task queue to promote the main thread to form new macro tasks; If not, read the task event of the task queue and push the main thread to form a new macro task.

3. Execute the event task of the new macro task, and then check if there are any microtasks that can be executed, and so on.

This is the detailed event loop with the addition of microtasks. If you don’t understand it, then do a comprehensive analysis of the initial 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');
Copy the code

The execution process is as follows:

1. After the code block is parsed and precompiled, it enters the execution stage, when the main thread of JS engine is executed to console.log(‘script start’); The main thread of the JS engine considers the task to be a synchronization task, so it immediately executes the output script start, and then continues down.

SetTimeout (function() {console.log(‘setTimeout’); }, 0); , the main thread of the JS engine considers setTimeout as an API of asynchronous task, so it applies to the browser kernel process to start the timer thread for timing and control of the setTimeout task. As W3C stipulated in HTML standard that setTimeout interval below 4ms is 4ms, when the timer thread reaches 4ms, the callback handler is pushed into the task queue to wait for the main thread to execute, and then the JS engine main thread continues to execute.

Promise.resolve().then(function() {console.log(‘promise1’); }).then(function() { console.log(‘promise2’); }); The main thread of the JS engine considers the Promise to be a microtask, which divides the task into microtasks waiting to be executed.

Console. log(‘script end’); The main thread of the JS engine considers this task to be a synchronous task, so it immediately executes the output script end.

5. When macro tasks on the main thread are completed, it starts to detect the existence of executable microtasks. If a Promise microtask is detected, execute it immediately and output promisE1 and promisE2

6. After the execution of the microtask, the main thread begins to read the event task setTimeout in the task queue, push the main thread to form a new macro task, and then execute it in the main thread and output setTimeout

Final output:

script start
script end
promise1
promise2
setTimeout
Copy the code

Four,

The above is the whole process of JS engine execution, the execution process of JS engine is not complicated, as long as more thinking and more research can be understood, after understanding the process can improve the understanding of JS to a certain extent.

5. References

Tasks, microtasks, queues and schedules

Six, reference

Javascript you Don’t Know (Volume 1)

All kinds of benefits

1, byte push benefits

  • Reply “school admission” to get internal push code
  • Reply “Social recruitment” to get internal promotion
  • Reply “intern” to get internal push

There will be more benefits later

2. Learning materials welfare

Reply “Algorithm” to obtain algorithm learning materials

3. One question of the day

1. JavaScript && ES6

  • Q: What is the understanding of event flow, event handler and event object in JS?

  • 第 16 题 : How to perform client detection comprehensively in JS?

  • Interviewer: What are the methods for judging the JS type?

  • Interviewer: Tell me about your creation and extension of JS objects

  • [‘1’, ‘2’, ‘3’]. Map (parseInt) output, the reason, and the extension?

  • Q: What is the execution process of the JS engine?

  • Q: What is the execution process of JS engine?

  • Q: Tell me more about the JS data type

  • Q: What is your understanding of ES6 proxy?

  • Interviewer: What is the difference between “for in” and “for of”?

  • 6. How can Async/Await Async/Await Async?

  • 3. “Question of the Day” The interviewer asks you what you think of Promise?

  • In ES6, why do we use Symbol?

2. Browser

  • 9. Doesn’t requestAnimationFrame smell good?

3, Vue

  • How does VUE data binding work?

4, algorithm

  • Question 4: How to find repetitive elements in a scientific and efficient way?

5, Http

  • 1. “How does an interview question trigger deep soul searching?”

Thank you for your support

1, if you like, you can “share, like, watch” three lian oh.

2, author nickname: SaucXS, songEagle, Songbao write code. A front-end engineer of Bytedance, an author who is working hard to grow, Star Sea, which has a promising future, will work in all departments of Bytedance.

3, long press the picture below, pay attention to “Songbao write code”, it is to obtain the development knowledge system construction, selected articles, project actual combat, laboratory, a daily interview question, advanced learning, thinking about career development, involving JavaScript, Node, Vue, React, browser, HTTP and other fields, I hope it can help you. We grow up together