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.
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
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:
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:
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).
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!