1.事件循環與 Promise 執行順序
案例 1:基礎 Promise 同步異步區分
console.log(1);
new Promise(resolve => {console.log(2);resolve();console.log(3);
}).then(() => console.log(4));
console.log(5);
輸出順序:1,2,3,5,4
同步代碼優先執行:
- 先執行?
console.log(1)
?→ 輸出?1
- 遇到?
new Promise
,執行構造函數里的同步代碼:console.log(2)
?→ 輸出?2
;resolve()
?標記 Promise 為已完成,但不影響當前同步流程;接著?console.log(3)
?→ 輸出?3
- 繼續執行同步代碼?
console.log(5)
?→ 輸出?5
微任務隊列執行:
- 同步代碼執行完后,檢查微任務隊列(Promise 的?
then
?回調屬于微任務),執行?then
?里的?console.log(4)
?→ 輸出?4
先同步再異步,微任務高于宏任務!
案例 2:微任務(Promise) vs 宏任務(setTimeout)
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
?輸出順序:1, 4, 3, 2
同步代碼階段:
console.log(1)
?→ 輸出?1
- 遇到?
setTimeout
(宏任務),丟進宏任務隊列,暫不執行 - 遇到?
Promise.resolve().then
(微任務),丟進微任務隊列 console.log(4)
?→ 輸出?4
微任務執行階段:
- 同步代碼跑完,先清空微任務隊列?→ 執行?
then
?回調?console.log(3)
?→ 輸出?3
宏任務執行階段:
- 微任務清空后,執行宏任務隊列里的?
setTimeout
?→ 輸出?2
先同步再異步,微任務高于宏任務!
2.then/catch 的錯誤捕獲邏輯
案例:Promise 鏈式調用的錯誤傳遞
Promise.reject("error").then(() => console.log("success")).catch(err => console.log(err));
執行流程拆解:
Promise.reject("error")
?直接生成一個已拒絕的 Promise- 鏈式調用的?
then
?回調:因為 Promise 狀態是 “拒絕”,then
?里的成功回調(() => console.log("success")
)會被跳過 - 后續的?
catch
?會捕獲到前面傳遞的錯誤("error"
),執行?console.log(err)
?→ 輸出?error
catch兜底,then分流!(catch
?主打 “兜底捕獲未處理錯誤”,then
?負責 “成功 / 失敗的流程分流)