This article mainly introduces the JS browser event loop mechanism, which has certain reference value. Now I share it with you. Friends in need can refer to it.
Let’s first understand some conceptual content.
A process is an independent resource allocated by the system and the basic unit of CPU resource allocation. A process is composed of one or more threads.
Thread is the execution flow of the process and the basic unit of CPU scheduling and dispatch. Multiple threads in the same process share the resources of the process.
The browser is multi-process, and each tab label in the browser represents an independent process (not necessarily , because multiple blank tab labels will be merged into one process), the browser kernel (browser rendering process) is one of the browser's multi-processes.
The browser kernel has multiple threads working.
#When http makes a request, a request thread will be opened.
After the request is completed and the result is obtained, the request callback function is added to the task queue and waits for processing by the JS engine.
The browser timing counter is not counted by the JS engine, and blocking will lead to inaccurate timing.
Enable the timer to trigger the thread to time and trigger the timing. After the timing is completed, it will be added to the task queue and wait for processing by the JS engine.
When an event meets the triggering conditions and is triggered, the thread will add the corresponding event callback function to the end of the task queue and wait for processing by the JS engine.
Single-threaded work, responsible for parsing and running JavaScript scripts.
and the GUI rendering thread are mutually exclusive. If JS takes too long to run, the page will be blocked.
Responsible for rendering the page, parsing HTML, CSS to form a DOM tree, etc. This thread will be called up when the page is redrawn or reflow is caused by some operation.
and the JS engine thread are mutually exclusive. When the JS engine thread is working, the GUI rendering thread will be suspended, and the GUI update will be placed in the JS task queue, waiting. The JS engine thread continues execution when it is idle.
GUI rendering thread:
JS engine thread:
Event triggering thread:
Timer trigger thread:
http request thread:
The JavaScript engine is single-threaded, which means that only one task can be executed at a time. Other tasks must be queued in order to be executed. Only the current task is executed. After completion, the next task will be executed.
The Web-Worker API was proposed in HTML5, mainly to solve the problem of page blocking, but it did not change the single-threaded nature of JavaScript. Learn about Web-Workers.
JavaScript event loop mechanism is divided into browser and Node event loop mechanisms. The implementation technologies of the two are different. Browser Event Loop is a specification defined in HTML. Node Event Loop is implemented by the libuv library. The main focus here is the browser part.
Javascript has a main thread and a call-stack call stack (execution stack). All tasks will be placed on the call stack to wait for execution by the main thread.
JS call stack
JS call stack is a last-in-first-out data structure. When a function is called, it is added to the top of the stack. After execution is completed, the function is removed from the top of the stack until the stack is cleared.
Synchronous tasks, asynchronous tasks
JavaScript tasks in a single thread are divided into synchronous tasks and asynchronous tasks. Synchronous tasks will be queued in order in the call stack waiting for the main thread to execute, while asynchronous tasks will add the registered callback function to the task queue (message queue) after the asynchronous result is available, waiting for the main thread to be idle, that is, in the stack When cleared, it is read into the stack and waits for execution by the main thread. The task queue is a first-in-first-out data structure.
Event Loop
After all the synchronization tasks in the call stack have been executed and the stack has been cleared, it means that the main thread is idle and will go to the task queue at this time. A task is read in sequence and placed on the stack for execution. Every time the stack is cleared, it will read whether there are tasks in the task queue, and if there are tasks, it will be read and executed. The operation of reading and executing will form an event loop.
The delay number of milliseconds specified by the timer is actually not accurate, because the timer only puts the event into the task queue when the specified time is reached, and it must wait until the synchronized task and the event in the existing task queue After all executions are completed, the timer events will be read and executed on the main thread. There may be tasks that take a long time in the middle, so it is impossible to guarantee execution at the specified time.
Macro-task, micro-task
In addition to generalized synchronous tasks and asynchronous tasks, tasks in JavaScript single threads can be detailed Divided into macro tasks and micro tasks.
macro-task includes: script (overall code), setTimeout, setInterval, setImmediate, I/O, UI rendering.
Micro-task includes: process.nextTick, Promises, Object.observe, MutationObserver.
console.log(1); setTimeout(function() { console.log(2); }) var promise = new Promise(function(resolve, reject) { console.log(3); resolve(); }) promise.then(function() { console.log(4); }) console.log(5);
In the example, setTimeout and Promise are called task sources, and callback functions registered from different task sources will be put into different task queues.
After having the concepts of macro tasks and micro tasks, what is the execution order of JS? Should macro tasks or micro tasks come first?
In the first event loop, the JavaScript engine will execute the entire script code as a macrotask. After the execution is completed, it will detect whether there is a microtask in this loop. If it exists, it will start from the microtask in sequence. After all microtasks are read and executed in the task queue, the tasks in the task queue of the macrotask are read and executed, and then all microtasks are executed, and so on. The execution sequence of JS is the macro tasks-micro tasks in each event loop.
In the above example, in the first event loop, the entire code enters the main thread for execution as a macro task.
When setTimeout is encountered, the callback function will be placed in the task queue of the macro task after the specified time has passed.
When encountering a Promise, put the then function into the task queue of the microtask.
After the entire event loop is completed, it will detect whether there is a task in the task queue of the microtask, and execute it if it exists.
The first loop result is printed as: 1,3,5,4.
Then go to the task queue of the macro task and take out a macro task in order and put it on the stack for the main thread to execute. Then the macro task in this loop is the callback function registered by setTimeout. , after executing this callback function, it is found that there are no microtasks in this loop, and we are ready for the next event loop.
If it is detected that there are no tasks to be executed in the macro task queue, then the event loop will end.
The final result is 1,3,5,4,2.
The above is the entire content of this article. I hope it will be helpful to everyone’s study. For more related content, please pay attention to the PHP Chinese website!
Related recommendations:
The above is the detailed content of JS browser event loop mechanism. For more information, please follow other related articles on the PHP Chinese website!