A,Event Loop:
Also called event loop, it is a mechanism in the browser or Node environment to prevent javaScript from blocking when running in a single thread. As a single-threaded language, javascript itself is not asynchronous, but is provided by its host environment.
Ii. Micro tasks and macro tasks:
When javascript code runs, tasks are divided into two types, MacroTask/Task and microtask (MircoTask); Event Loop also divides Task queues into Task Queue and MircoTak Queue for MacroTask/Task and MircoTask respectively when executing and coordinating various tasks. As queues, Task queues and MircoTak Queues also have Queue characteristics: FIFO — first in first out.
1. MircoTask
Microtask is not specified in the HTML standard, but it is developed in four ways:
- Then, catch, and finally in promises
- MutationObserver (API for monitoring DOM changes)
- Object.observe(Discard: Listen for changes in standard objects)
- Process.nexttick (Node environment, also commonly known as microtasks)
2. MacroTask/Task
Basically, we classify all non-mircotask tasks in javascript as macro tasks, such as:
- All the code in script
- DOM manipulation
- User interaction
- All network requests
- Timers related to setTimeout and setInterval
3, javascript runtime
Javascript Runtime: Provides objects or mechanisms for javascript to interact with the outside world. It is an execution environment for javascript. Javascript execution creates a main thread and a call-stack (execution stack, last in, first out), and all tasks are placed on the call stack/execution stack to wait for the main thread to execute. Its operating mechanism is as follows:
-
1) The main thread executes all code from top to bottom;
-
2) The synchronization task is executed directly into the main thread;
-
3) The asynchronous task enters the Event Table. When the asynchronous task has a result, the corresponding callback function is registered and added to the Event Queue.
-
4) After the main thread is idle, the task is read from the Event Queue (FIFO) and put into the main thread for execution;
-
5) The Event Queue task placed on the main thread continues from the first step, and so on.
The execution process of the above steps is called an Event Loop. The figure above shows the complete process of the Event Loop.
3. Event Loop in browser environment
The execution mechanism of Event Loop is different in different execution environments. For example, Chrome and Node.js both use V8 Engine: V8 implements and provides all the data types, operators, objects, and methods in the ECMAScript standard (note that there is no DOM). But their Runtime is different: Chrome provides Window, DOM, node.js require, process, and so on. We need to sort out the relationship between synchronous, asynchronous, microtask and macro task before we can understand the specific representation of Event Loop in browser!
1. Synchronous, asynchronous, macro and micro tasks
Macro task and micro task are relative. According to the sequence of code execution cycle, the code execution is understood in layers. In each layer (once) event cycle, the whole code block is first regarded as a macro task. Promise (then, catch, finally), MutationObserver and process. nextTick are microtasks in the macro task layer. The synchronous code in the macro task enters the main thread for immediate execution, and the non-micro task asynchronous execution code in the macro task enters the call stack for execution as the macro task of the next cycle; At this point, the call stack is divided into two kinds of queues waiting to execute, the higher priority of the local layer cyclic MicroTask Queue, and the lower priority of the lower layer cyclic MacroTask Queue! Note: each/layer loop starts with the macro task and ends with the micro task;
2. Simple case analysis
console.log('script start');
setTimeout(() = > {
console.log('setTimeout');
}, 0)
new Promise((resolve) = > {
console.log('enter promise');
resolve();
})
.then(() = > {
console.log('promise then 1');
})
.then(() = > {
console.log('promise then 2');
})
console.log('script end');
Copy the code
Start with code analysis: This is a simple and typical execution of a two-tier event loop, in which the analysis can be performed by following these steps:
-
First, distinguish the scope of macro tasks (the whole code);
-
Console. log(‘script start’); And the console. The log (” enter promise “); And the console log (‘ script end ‘); ; Asynchronous code blocks: setTimeout and then of the Promise (note: only then, catch, and finally execution of the Promise need to wait for the result, and the callback function passed in by the Promise is synchronous execution code);
-
3. Find the same level of microtasks (Promise’s then in code) and macro tasks (setTimeout in code) in the underlying event loop in asynchrony
-
4, macro task synchronization code priority into the main thread, according to the top-down order to complete execution; The output sequence is:
Script start Enter promise script endCopy the code
-
5. When the main thread is idle, perform the layer’s microtasks
// Layer microtask queue code executes output Promise then 1 Promise then 2Copy the code
-
6, the first layer of the event loop ends, the second layer of the event loop (setTimeout contains the execution code, only a synchronization code)
// Layer 2 macro task queue code executes output setTimeoutCopy the code
After comprehensive analysis, the data results are as follows:
// Layer 1 macro task code executes output script start enter promise script end // Layer 1 macro task queue code executes output Promise then 1 Promise then 2 // Layer 2 macro task queue code executes output setTimeoutCopy the code
3. Complex cases
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('3');
resolve();
}).then(function() {
console.log('4')})setTimeout(function() {
console.log('5');
new Promise(function(resolve) {
console.log('6');
resolve();
}).then(function() {
console.log('7')})})console.log('14');
})
new Promise(function(resolve) {
console.log('8');
resolve();
}).then(function() {
console.log('9')})setTimeout(function() {
console.log('10');
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')})})console.log('13')
Copy the code
Analysis: As shown in the draft below, macro task queue is marked a in the upper left corner, and micro task queue is marked I in the upper left corner. In the same layer cycle, macro task is executed first and then micro task is executed. The non-microtask asynchronous code block in the macro task of this layer enters the next loop as the macro task of the lower loop, and so the loop is executed.
Running results:
13-1-8 - > > > 9 - > 2 - > 3 - > 14 - > 4-10-11-12 - > > > > 5 - > 6 - > 7Copy the code