|
|
|
@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
# JS 事件循环 (Event Loop)
|
|
|
|
|
|
|
|
## 知识点总结(个人整理)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 执行顺序
|
|
|
|
|
|
|
|
1. 同步任务
|
|
|
|
|
|
|
|
2. 微任务队列(执行完毕后会再次检查微任务队列,直到清空微任务队列为止)
|
|
|
|
|
|
|
|
3. 第一个宏任务
|
|
|
|
|
|
|
|
4. 再次检查微任务队列,有就清空
|
|
|
|
|
|
|
|
5. 第二个宏任务
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
...重复上面步骤直到清空宏任务队列
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 代码示例
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
console.log("同步1");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
|
|
|
console.log("微任务1");
|
|
|
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
|
|
|
console.log("微任务1-1");
|
|
|
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
|
|
|
console.log("微任务2-1");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
console.log("宏任务1");
|
|
|
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
|
|
|
console.log("宏任务1-微任务");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log("同步2");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
|
|
|
console.log("微任务2");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
console.log("宏任务2");
|
|
|
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log("同步3");
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
同步1
|
|
|
|
|
|
|
|
同步2
|
|
|
|
|
|
|
|
同步3
|
|
|
|
|
|
|
|
微任务1
|
|
|
|
|
|
|
|
微任务2
|
|
|
|
|
|
|
|
微任务1-1
|
|
|
|
|
|
|
|
微任务2-1
|
|
|
|
|
|
|
|
宏任务1
|
|
|
|
|
|
|
|
宏任务1-微任务
|
|
|
|
|
|
|
|
宏任务2
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 知识点总结(以下为AI整理)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 为什么会有事件循环?
|
|
|
|
|
|
|
|
JavaScript 是单线程的,为了协调事件、用户交互、脚本、UI 渲染、网络等,必须使用事件循环。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 宏任务 (Macrotasks) 与 微任务 (Microtasks)
|
|
|
|
|
|
|
|
* **宏任务**: script (整体代码), setTimeout, setInterval, setImmediate (Node.js), I/O, UI rendering.
|
|
|
|
|
|
|
|
* **微任务**: Promise.then, process.nextTick (Node.js), MutationObserver.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 执行顺序
|
|
|
|
|
|
|
|
1. 执行一个宏任务(栈为空,执行整体 script 代码)。
|
|
|
|
|
|
|
|
2. 执行过程中遇到微任务,将其加入微任务队列。
|
|
|
|
|
|
|
|
3. 宏任务执行完毕,立即依次执行当前微任务队列中的所有微任务。
|
|
|
|
|
|
|
|
4. 微任务执行完毕,如果有 UI 渲染需求,则进行渲染。
|
|
|
|
|
|
|
|
5. 检查是否有宏任务,如果有,取出下一个宏任务,回到第 1 步。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 代码演示
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
|
|
console.log('script start');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
|
|
|
console.log('setTimeout');
|
|
|
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Promise.resolve().then(function() {
|
|
|
|
|
|
|
|
console.log('promise1');
|
|
|
|
|
|
|
|
}).then(function() {
|
|
|
|
|
|
|
|
console.log('promise2');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('script end');
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**预期输出顺序:**
|
|
|
|
|
|
|
|
1. script start
|
|
|
|
|
|
|
|
2. script end
|
|
|
|
|
|
|
|
3. promise1
|
|
|
|
|
|
|
|
4. promise2
|
|
|
|
|
|
|
|
5. setTimeout
|