在前端開發中,**宏任務(Macro Task)**和**微任務(Micro Task)**是 JavaScript 事件循環(Event Loop)中的兩個重要概念。它們決定了異步代碼的執行順序。
---
### 1. **事件循環(Event Loop)**
JavaScript 是單線程的,通過事件循環機制處理異步任務。事件循環的核心是:
- **主線程**:執行同步代碼。
- **任務隊列**:存放異步任務的回調函數。
- **事件循環**:不斷檢查任務隊列,將任務推入主線程執行。
任務隊列分為兩種:
- **宏任務隊列**:存放宏任務。
- **微任務隊列**:存放微任務。
---
### 2. **宏任務(Macro Task)**
宏任務是指需要較長時間執行的任務,通常包括:
- `setTimeout` 和 `setInterval` 的回調。
- `setImmediate`(Node.js 特有)。
- `requestAnimationFrame`(瀏覽器特有)。
- I/O 操作(如文件讀寫、網絡請求)。
- UI 渲染(瀏覽器特有)。
**執行時機**:每次事件循環中,主線程會執行一個宏任務,然后檢查微任務隊列。
---
### 3. **微任務(Micro Task)**
微任務是指需要盡快執行的任務,通常包括:
- `Promise` 的回調(`then`、`catch`、`finally`)。
- `MutationObserver`(監聽 DOM 變化)。
- `process.nextTick`(Node.js 特有)。
**執行時機**:每次宏任務執行完畢后,事件循環會清空微任務隊列中的所有任務,然后再執行下一個宏任務。
---
### 4. **執行順序**
事件循環的執行順序如下:
1. 執行主線程的同步代碼。
2. 執行當前宏任務。
3. 清空微任務隊列中的所有任務。
4. 執行 UI 渲染(瀏覽器)。
5. 執行下一個宏任務。
---
### 5. **代碼示例**
```javascript
console.log('1. 同步代碼'); // 同步代碼,立即執行
setTimeout(() => {
? console.log('4. 宏任務 - setTimeout'); // 宏任務
}, 0);
Promise.resolve().then(() => {
? console.log('3. 微任務 - Promise'); // 微任務
});
console.log('2. 同步代碼'); // 同步代碼,立即執行
```
**輸出結果**:
```
1. 同步代碼
2. 同步代碼
3. 微任務 - Promise
4. 宏任務 - setTimeout
```
**解釋**:
1. 同步代碼立即執行。
2. `Promise` 的微任務在同步代碼之后、宏任務之前執行。
3. `setTimeout` 的宏任務在微任務之后執行。
---
### 6. **宏任務和微任務的區別**
| 特性 ? ? ? ? ? ?| 宏任務(Macro Task) ? ? ? ? ? ? ? | 微任務(Micro Task) ? ? ? ? ? ? ? |
|-----------------|------------------------------------|------------------------------------|
| **執行時機** ? ? | 每次事件循環執行一個宏任務 ? ? ? ? | 每次宏任務執行后清空微任務隊列 ? ? |
| **常見任務** ? ? | `setTimeout`、`setInterval`、I/O ? | `Promise`、`MutationObserver` ? ? ?|
| **優先級** ? ? ? | 較低 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 較高 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
| **隊列類型** ? ? | 宏任務隊列 ? ? ? ? ? ? ? ? ? ? ? ? | 微任務隊列 ? ? ? ? ? ? ? ? ? ? ? ? |
---
### 7. **實際應用**
- **優化性能**:將高優先級任務放入微任務隊列,確保盡快執行。
- **避免阻塞**:將耗時任務放入宏任務隊列,避免阻塞主線程。
- **控制執行順序**:通過微任務和宏任務的特性,控制異步代碼的執行順序。
---
### 總結
- **宏任務**:需要較長時間執行的任務,如 `setTimeout`、I/O 操作。
- **微任務**:需要盡快執行的任務,如 `Promise`、`MutationObserver`。
- **執行順序**:同步代碼 → 微任務 → 宏任務 → UI 渲染 → 下一個宏任務。
理解宏任務和微任務的機制,有助于更好地掌握 JavaScript 的異步編程和事件循環。