1.JS is single threaded
The code in JS is serial, The previous execution is not completed, and the later cannot be executed
2. Execution sequence
- The program will execute all synchronization codes from top to bottom
- If asynchronous code is encountered during execution, the asynchronous code will be placed in the event loop
- When all synchronization code is executed, JS will continuously detect Whether the asynchronous code in the event loop meets the condition
- Once the condition is met, the asynchronous code that meets the condition is executed
3. Macro and micro tasks:
In the asynchronous code of JS, it distinguishes between "macro task" and "micro task"
Macro task: Macro / big, It can be understood as a time-consuming and slow task
Microtask: Micro / small meaning, It can be understood as a relatively less time-consuming and less slow task
4. Common macro tasks and micro tasks:
MacroTask: setTimeout, setInterval, setImmediate (IE only)
Basic usage of setlmmediate:
setImmediate(function() { console.log("setImmediate"); }); console.log("Synchronization code Start"); console.log("Synchronization code End");
setImmediate and setTimeout, setInterval difference:
setImmediate cannot set the delay time, And can only be executed once; Ie is unique, that is, it can only take effect in IE browser
MicroTask: Promise, MutationObserver , process.nextTick (unique to node) ...
Basic usage of MutationObserver:
MutationObserver is specifically used to listen for changes in nodes
<div></div> <button class="add">Add node</button> <button class="del">Delete node</button>
let oDiv = document.querySelector("div"); let oAddBtn = document.querySelector(".add"); let oDelBtn = document.querySelector(".del"); oAddBtn.onclick = function() { let op = document.createElement("p"); op.innerText = "I'm a paragraph"; oDiv.appendChild(op); } oDelBtn.onclick = function() { let op = document.querySelector("p"); oDiv.removeChild(op); } //Listen -- as long as you listen to the node you add or delete, the following statement will be printed let mb = new MutationObserver(function() { console.log("Yes"); }); //Select the object to listen to // This means listening for changes in oDiv child nodes mb.observe(oDiv, { "childList": true }); console.log("Synchronization code Start"); console.log("Synchronization code End");
Note:
- All macro tasks and micro tasks will be placed in their own execution queue, That is, there is a macro task queue and a micro task queue
- All tasks placed in the queue adopt the "first in first out" principle, That is, multiple tasks meet the conditions at the same time, Then it will be executed first and put in first
5. Complete execution sequence
- Execute all synchronization codes from top to bottom
- Macro tasks encountered during execution are placed in the macro task queue, and micro tasks encountered are placed in the micro task queue
- When all synchronization code is executed, Execute all callbacks that meet the requirements in the micro task queue
- After all callbacks meeting the requirements of the micro task queue are executed, Execute all callbacks in the macro task queue that meet the requirements
- ... ...
Example,
// 1. Define a macro task setTimeout(function() { console.log("setTimeout1"); }, 0); // 2. Define a micro task Promise.resolve().then(function() { console.log("Promise1"); }); console.log("Synchronization code Start"); Promise.resolve().then(function() { console.log("Promise2"); }); setTimeout(function() { console.log("setTimeout2"); }, 0); console.log("Synchronization code End");
Execution process:
Note:
Every time a macro task is executed, it will immediately check whether the micro task queue has been emptied, If not, empty it immediately
Example,
// 1. Define a macro task setTimeout(function() { console.log("setTimeout1"); // 2. Define a micro task p1 Promise.resolve().then(function() { console.log("Promise1"); }); // 2. Define a micro task p2 Promise.resolve().then(function() { console.log("Promise2"); }); }, 0); // 1. Define a macro task setTimeout(function() { console.log("setTimeout2"); // 2. Define a micro task p3 Promise.resolve().then(function() { console.log("Promise3"); }); // 2. Define a micro task p4 Promise.resolve().then(function() { console.log("Promise4"); }); }, 0);
Execution process:
Example 2,
// 1. Define a macro task setTimeout(function() { console.log("setTimeout1"); // 2. Define a micro task p2 Promise.resolve().then(function() { console.log("Promise2"); }); // 2. Define a micro task p3 Promise.resolve().then(function() { console.log("Promise3"); }); }, 0); // 2. Define a micro task p3 Promise.resolve().then(function() { console.log("Promise1"); // s2 setTimeout(function() { console.log("setTimeout2"); }); // s3 setTimeout(function() { console.log("setTimeout3"); }); });
Execution process: