JavaScript event loop mechanism, macro tasks and micro tasks (principle analysis)

1. Event Loop
Event Loop is an event loop, which refers to 浏览器or Node (host) a mechanism that solves javaScriptsingle-threaded runtime without blocking, that is, we often use the principle of asynchrony.

2. Synchronous tasks and asynchronous tasks Single-threaded tasks are divided into synchronous tasks and asynchronous tasks. Synchronous tasks will wait for the main thread to execute sequentially in the call stack. Asynchronous tasks will register callback functions
Javascript after the asynchronous task has a result. When it is put into the task queue and waits for the main thread to be idle (the call stack is cleared), it is read into the stack and waits for the execution of the main thread .
The task in the main thread is empty after execution, and will go to the Event Queue to read the corresponding function and enter the main thread for execution. The above process will continue to repeat, which is often said Event Loop(event loop)

Note: The queue (Queue) follows the first-in-first-out principle

3. Macro task: ( macrotask)
The macro task is initiated by the host ( 浏览器windowor ). Common macro tasks in front-end development: including , , , .Node
整体代码scriptsetTimeoutsetIntervalsetImmediate

4. Micro-task: ( microtask)
The micro-task JavaScriptis initiated by itself.
Common micro-tasks in front-end development: PromiseProcess.nextTick(Node独有)

Let's use a classic topic for specific analysis:

console.log('1');

// 定义注解 setTimeout_1 用于下文使用方便
setTimeout(function() {
    
    
    console.log('2');
    process.nextTick(function() {
    
    
        console.log('3');
    })
    new Promise(function(resolve) {
    
    
        console.log('4');
        resolve();
    }).then(function() {
    
    
        console.log('5')
    })
})
process.nextTick(function() {
    
    
    console.log('6');
})
new Promise(function(resolve) {
    
    
    console.log('7');
    resolve();
}).then(function() {
    
    
    console.log('8')
})

// setTimeout_2
setTimeout(function() {
    
    
    console.log('9');
    process.nextTick(function() {
    
    
        console.log('10');
    })
    new Promise(function(resolve) {
    
    
        console.log('11');
        resolve();
    }).then(function() {
    
    
        console.log('12')
    })
})

// 输出结果:  1 7 6 8 2 4 3 5 9 11 10 12

1. The analysis of the first round of event loop process is as follows:

(1) Enter the main thread 整体scriptas the first macro task , console.log('1')execute synchronously, and output 1
(2) Execute setTimeout_1asynchronously, distribute its callback function to the macro task Event Queue(queue)
(3) Execute asynchronously, distribute its callback function to process.nextTickmicrotasks (4) Execution , Promise is executed immediately after it is created, so execution, output , is asynchronous, and it is distributed to microtasks (5) Execution is asynchronous, and it is distributed to macro tasks (queues)Event Queue
new Promiseconsole.log('7')7.thenEvent Queue
setTimeout_2Event Queue

The situation of each Event Queue at the end of the first round of event loop macro tasks: the
output results of the synchronization code are: 1, 7
macro tasks Event Queue: setTimeout_1, setTimeout_2
micro tasks Event Queue: 整体scriptmedium process.nextTick,new Promise().then()

The task in the main thread is empty after execution, it will go to the microtask Event Queue to read the corresponding function, and enter the main thread for execution: at
this time, the execution process.nextTickand new Promise().then()output results are: 6, 8

Output results after the first round: 1, 7, 6, 8

Key point: the microtask Event Queue is empty after execution, and will go to the macrotask Event Queue to read the corresponding function. At this point, the first round of event loop is completely over, and the second round of event loop begins

2. The analysis of the second round of event loop process is as follows: ( 宏任务Event Queuein progress setTimeout_1)

(1) setTimeout_1Enter the main thread, console.log('2')execute synchronously, and output 2
(2) Execute process.nextTickasynchronously, and distribute its callback function to microtasks (3) Execute , execute immediately Event Queueafter the Promise is created, so execution, output , are asynchronous, and distribute it to microtasks on task
new Promiseconsole.log('4')4.thenEvent Queue

The situation of each Event Queue at the end of the second round of event loop macro tasks:
the output of the synchronization code is: 2, 4
macro tasks Event Queue: setTimeout_2
micro tasks Event Queue: setTimeout_1medium process.nextTick,new Promise().then()

The task in the second round of the main thread is empty after execution, and will go to the microtask Event Queue to read the corresponding function

Output results after the second round: 2, 4, 3, 5

The second round of event loop is completely over, and the third round of setTimeout_2event loop begins

3. The third round of event loop process analysis is as follows: ( 宏任务Event Queuein progress setTimeout_2)

(1) setTimeout_2Enter the main thread, console.log('9')execute synchronously, and output 9
(2) Execute process.nextTickasynchronously, and distribute its callback function to microtasks (3) Execute , execute immediately Event Queueafter the Promise is created, so execution, output , are asynchronous, and distribute it to microtasks on task
new Promiseconsole.log('11')11.thenEvent Queue

The task in the third round of the main thread is empty after execution, and will go to the microtask Event Queue to read the corresponding function

Output results after the third round: 9, 11, 10, 12

The third round of execution is completed, and the task queue is empty so far. The entire code has a total of three event loops.

The complete output is 1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10, 12.

Summary: 整体scriptEnter the main thread as the first macro task and perform the first event loop. If a macro task is encountered, its callback function will be distributed to the macro task queue . If a micro task is encountered, its callback function will be distributed to in the microtask queue . After the synchronization code is executed, the microtask queue enters the main thread until the task execution is completed and becomes empty, and the next macrotask enters the main thread, which means that the second event loop starts. The above process will be repeated continuously until the execution of the macro task queue is empty, which is often referred to as the Event Loop(event loop) mechanism.

Guess you like

Origin blog.csdn.net/qq_44094296/article/details/125888078