Home  >  Article  >  Web Front-end  >  Technical Answer: JavaScript Execution Mechanism

Technical Answer: JavaScript Execution Mechanism

WBOY
WBOYforward
2022-01-14 17:23:171227browse

This article brings you some issues related to the execution mechanism in JavaScript. Whether it is work or an interview, we may often encounter scenarios where we need to know the execution order of the code. I hope it will be helpful to everyone.

Technical Answer: JavaScript Execution Mechanism

Processes and Threads

We all know that the core of the computer is the CPU, which is responsible for It handles all computing tasks; the operating system is the manager of the computer, responsible for task scheduling, resource allocation and management, and commanding the entire computer hardware; application programs are programs with certain functions, and programs run on the operating system. Up.

Process

#A process is a dynamic execution process of a program with independent functions on a data set. It is an operation An independent unit for resource allocation and scheduling in the system. It is the carrier for application running. The process is the smallest unit that can own resources and run independently. It is also the smallest unit for program execution.

Characteristics of a process:

  • Dynamicity: A process is an execution process of a program. It is temporary, has a life span, and is generated dynamically. Dynamic death;

  • Concurrency: Any process can be executed concurrently with other processes;

  • Independence: The process is a system resource An independent unit of allocation and scheduling;

  • Structural: The process consists of three parts: program, data and process control block.

Thread

A thread is a single sequential control process in program execution and is the smallest unit of program execution flow. , is the basic unit of processor scheduling and dispatch. A process can have one or more threads, and each thread shares the memory space of the program (that is, the memory space of the process). A standard thread consists of thread ID, current instruction pointer (PC), registers and stack. The process consists of memory space (code, data, process space, open files) and one or more threads.

The difference between process and thread

  • Thread is the smallest unit of program execution, and process is the smallest unit of resources allocated by the operating system;

  • A process consists of one or more threads. Threads are different execution routes of code in a process;

  • Processes are independent of each other, but each thread under the same process The memory space of the program (including code segments, data sets, heaps, etc.) and some process-level resources (such as open files and signals) are shared between them, and the processes are invisible to each other;

  • Scheduling and switching: Thread context switching is much faster than process context switching.

#Why is JS single-threaded?

JavaScript has been used as a scripting language for browsers since its birth. It is mainly used to handle user interaction and operate DOM. This determines that it can only be single-threaded, otherwise it will Brings very complex synchronization issues.

For example: If JS is multi-threaded, one thread wants to modify a DOM element, and another thread wants to delete the DOM element, then the browser does not know who to listen to. So in order to avoid complexity, JavaScript has been designed to be single-threaded since its birth.

In order to take advantage of the computing power of multi-core CPUs, HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and must not operate the DOM. Therefore, this new standard does not change the single-threaded nature of JavaScript

Browser Principle

As a front-end engineer, browsers must be familiar to you , and the browser is multi-process.

Browser components

  • User interface: including address bar, forward/back/refresh/bookmarks

  • Browser engine: transmits instructions between the user interface and the rendering engine

  • Rendering engine: used to draw the requested content

  • Network: used to complete network calls, such as http requests, it has a platform-independent interface and can work on different platforms

  • JavaScript interpreter: used Parse and execute JavaScript code

  • User interface backend: used to draw basic widgets, such as combo boxes and windows, and the underlying user interface of the operating system

  • Data storage: It belongs to the persistence layer. The browser saves various data similar to cookies on the hard disk. HTML5 defines web database technology, which is a lightweight and complete client-side storage technology

Note: Unlike most browsers, each tab of the Google Chrome browser corresponds to a rendering engine instance. Each tab is an independent process

What processes does the browser contain

##Browser process

  • The main process of the browser (responsible for coordination and control), this process has only one

  • Responsible for browser interface display and user interaction. Such as forward, backward, etc.

  • Responsible for the management of each page, creating and destroying other processes

  • The memory obtained by the rendering (Renderer) process Bitmap (bitmap), drawn to the user interface

  • Management of network resources, downloads, etc.

Third-party plug-in process

Responsible for managing third-party plug-ins

GPU process

Responsible for 3D rendering and hardware acceleration (at most one)

Rendering process

Responsible for page document parsing, execution and rendering

What threads does the rendering process include

GUI rendering thread

Mainly responsible for parsing HTML, CSS, building DOM tree, layout, drawing, etc.

This thread is mutually exclusive with the JavaScript engine thread. When the JavaScript engine is executed thread, the GUI rendering thread will be suspended. When the task queue is idle, the main thread will execute GUI rendering

JavaScript engine thread

Mainly responsible for processing JavaScript scripts , execute code (such as V8 engine)

The browser can only have one JS engine thread running the JS program at the same time, that is, JS is a single-threaded

The JS engine thread and the GUI rendering thread are mutually exclusive Rejected, so the JS engine will block page rendering

Timing trigger thread

Responsible for executing timer functions (setTimeout, setInterval)

Browser The timing counter is not counted by the JS engine (because JS is single-threaded, if it is blocked, it will affect the accuracy of the counter)

Time and trigger timing through a separate thread (after timing is completed, add to In the event queue of the event triggering thread, wait for the JS engine to be idle and execute). This thread is the timed trigger thread, also called the timer thread

W3C stipulates in the HTML standard that the setTimeout is required to be less than 4ms The time interval is counted as 4ms

Event triggering thread

Responsible for handing prepared events to the JS engine thread for execution

When the event is triggered, This thread will add the corresponding event to the end of the pending queue and wait for the JS engine to process

Asynchronous request thread

After the XMLHttpRequest connection, the browser will open a When the thread

detects the request status change, if there is a corresponding callback function, the asynchronous request thread will generate a status change event and put the corresponding callback function into the queue to wait for the JS engine to execute

Synchronization and asynchronous

Since JavaScript is single-threaded, this determines that its tasks cannot only be synchronous tasks. If those tasks that take a long time are also Executing synchronous tasks will cause page blocking, so JavaScript tasks are generally divided into two categories:

Synchronous tasks

Synchronous tasks refer to the main thread For tasks queued for execution, the next task can only be executed after the previous task is executed;

Asynchronous tasks

Asynchronous tasks refer to tasks that do not enter the main thread but For tasks that enter the "task queue" (Event queue), only when the "task queue" notifies the main thread that an asynchronous task can be executed will the task enter the main thread for execution.

Common asynchronous tasks: timer, ajax, event binding, callback function, promise, async await, etc.

  • Synchronous and asynchronous tasks enter different executions respectively." "Place", enter the main thread synchronously, enter the Event Table asynchronously and register the function.

  • When the things specified in the Event Table are completed, this function will be moved to the Event Queue.

  • The task in the main thread is empty after execution. It will go to the Event Queue to read the corresponding function and enter the main thread for execution.

  • The above process will be repeated continuously, which is often called Event Loop.

  • We can’t help but ask, how do we know that the main thread execution stack is empty? There is a monitoring process in the js engine, which will continuously check whether the main thread execution stack is empty. Once it is empty, it will go to the Event Queue to check whether there is a function waiting to be called.

Macro tasks and micro tasks

In addition to synchronous tasks and asynchronous tasks in a broad sense, JavaScript also has more detailed tasks Task definition:

  • Macro-task: including global code, setTimeout, setInterval

  • Micro-task : new Promise().then(callback) process.nextTick()

Different types of tasks will enter different task queues:

Technical Answer: JavaScript Execution Mechanism

The order of the event loop determines the execution order of js code. After entering the overall code (macro task), the first cycle starts. Then execute all microtasks. Then start from the macro task again, find one of the task queues to be executed, and then execute all micro tasks.

Execution stack and task queue

Execution stack

JavaScript code is executed in the execution context. There are three execution contexts in JavaScript:

  • Global execution context

  • Function Execution context, a function execution context will be created when a JS function is called

  • eval execution context, the context generated by the eval function (less used)

Generally speaking, our JS code has more than one context, so what is the execution order of these contexts?

We all know that the stack is a last-in-first-out data structure. The execution stack in our JavaScript is such a stack structure. When the JS engine executes the code, it will generate a global context and push it When a function call is encountered, a function execution context is generated and pushed onto the execution stack. The engine starts executing the function from the top of the stack, and the execution context will pop up after execution.

function add(){
  console.log(1)
  foo()
  console.log(3)
}
function foo(){
  console.log(2)
}
add()

Let’s take a look at what the execution stack of the above code looks like:

Technical Answer: JavaScript Execution Mechanism

Task Queue

We mentioned earlier that all tasks in JavaScript are divided into synchronous tasks and asynchronous tasks. Synchronous tasks, as the name suggests, are tasks that are executed immediately. They generally enter the main thread directly for execution. Our asynchronous task enters the task queue and waits for the task in the main thread to be executed before executing it.

The task queue is an event queue, indicating that related asynchronous tasks can enter the execution stack. The main thread reads the task queue to read the events in it.

Queue is a first-in-first-out data structure.

We mentioned above that asynchronous tasks can be divided into macro tasks and micro tasks, so the task queue can also be divided into macro task queue and micro task queue

  • Macrotask Queue : Carry out relatively large work, common ones include setTimeout, setInterval, user interaction, UI rendering, etc.;

  • Microtask Queue: Carry out smaller work, common ones include Promise, Process. nextTick;

Event-Loop

Synchronous tasks are directly put into the main thread for execution, asynchronously Tasks (click events, timers, ajax, etc.) hang in the background for execution, waiting for I/O events to complete or behavioral events to be triggered.

The system executes asynchronous tasks in the background. If an asynchronous task event (or behavioral event is triggered), the task will be added to the task queue, and each task will be processed by a callback function.

Here asynchronous tasks are divided into macro tasks and micro tasks. Macro tasks enter the macro task queue, and micro tasks enter the micro task queue.

The tasks in the execution task queue are specifically completed in the execution stack. When all the tasks in the main thread are executed, read the micro-task queue. If there are micro-tasks, they will all be executed, and then go Reading the macro task queue

The above process will be repeated continuously, which is what we often call the event loop (Event-Loop).

Technical Answer: JavaScript Execution Mechanism

Example question verification

Let’s take a look at the question for verification

(async ()=>{
    console.log(1) 
  
    setTimeout(() => {
    console.log('setTimeout1')
    }, 0);
  
    function foo (){
        return new Promise((res,rej) => {
            console.log(2)
            res(3)
        })
    }
  
    new Promise((resolve,reject)=>{
    console.log(4)
    resolve() 
    console.log(5)
    }).then(()=> {
    console.log('6')
    })
  
    const res = await foo();
    console.log(res);
    console.log('7')
  
    setTimeout(_ => console.log('setTimeout2'))
})()

The printing order is: 1,4,5,2,6 ,3,7,setTimeout1,setTimeout2

Analysis:

The code is executed from top to bottom. It first encounters console.log(1), prints 1 directly, and then encounters a timer that belongs to a macro. Task, put it into the macro task queue

and then encounter a promise. Since new Promise is a synchronous task, it prints 4 directly. When it encounters resolve, which is the subsequent then function, it puts it into the micro task queue and prints it again. 5

Then execute await foo. There is a promise in the foo function. New promise is a synchronous task, so 2 will be printed directly. await returns a callback of promise, and the tasks after await are put into the microtask queue.

Finally encounter a timer and put it into the macro task queue

After the execution stack task is completed, first go to the micro task queue to obtain the micro task execution, execute the first micro task first, and print 6 , then execute the second microtask, print 3,7

After the microtask is executed, go to the macrotask queue to obtain the macrotask execution, and print setTimeout1,setTimeout2

[Related recommendations: javascript learning tutorial

The above is the detailed content of Technical Answer: JavaScript Execution Mechanism. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete