Day 20: 真相篇 —— Promise:給未來的一個承諾,解決你的回呼地獄
在非同步開發的世界中,當任務一個接著一個產生依賴時,傳統的「回呼函式(Callback)」往往會讓代碼像洋蔥一樣層層巢狀嵌套,形成難以維護的「回呼地獄(Callback Hell)」。本章節將揭開現代 JavaScript 管理非同步任務的關鍵核心 —— Promise。我們將透過矮人鐵匠「預約券」的生動比喻,探討 Pending(等待)、Fulfilled(成功)與 Rejected(失敗)三大狀態的不可逆轉換,掌握 .then() 與 .catch() 的鏈式傳遞(Chaining)心法,讓你的非同步邏輯從此清晰如詩。
本文同步分享於2026鐵人賽:JS 核心重構:勇者轉職傳說
孩子,在踏上今日的領地前,先坐下來喝杯酒吧。 修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。
我在每一站的盡頭都為你鋪設了 「
實戰演武場 CodePen」。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。 成功突圍後,別忘了帶著你的戰利品回到 「QuestBoard 佈告欄」。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。記住...
「 導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。 」
🛡️ 【公會大廳:導師的修煉導讀】
「導師,Day 19 告訴我 JS 不會等待耗時任務。但如果我真的需要那份資料才能繼續下一步怎麼辦?難道我只能在每個函式裡面套另一個函式,像洋蔥一樣越寫越深嗎?」
我從懷中掏出一張鑲著金邊的 「預約券 (Promise)」,遞給了眼前疲憊的小冒險者。
「孩子,這就是解決之道。當你委託矮人打造傳奇寶劍(發送非同步請求)時,他不會讓你站在門口乾等。他會給你一張券,這張券代表了一個『承諾』。你可以拿著它去處理別的事,而這張券會隨時追蹤進度,告訴你任務是成功了,還是炸爐了。」
今天,我們要學習如何簽下這份 「時空契約」。
💡 【導師講義:底層真相探究】
1. 什麼是 Promise?(未來的預約盒)
Promise 是一個對「未來某個時間點會完成」的任務的封裝。它就像一個有顏色的狀態燈:
- 🟡 Pending (等待中):矮人還在打鐵,結果未知。
- 🟢 Fulfilled / Resolved (成功):寶劍打好了!你可以憑券領取獎勵。
- 🔴 Rejected (失敗):矮人喝醉了,任務失敗。
2. 接住未來:捕捉結果的方法
當你手裡握著 Promise,你不再需要在那邊寫回呼函式 (Callback),而是使用更優雅的連動語法:
.then():當案子成功時,我要做什麼?.catch():當案子失敗時,我要怎麼反應?
| 特性 | 傳統回呼 (Callback) | 現代 Promise |
|---|---|---|
| 視覺結構 | 向右無限延伸 (洋蔥) | 向下優雅排列 (鏈條) |
| 錯誤處理 | 每一層都要手動寫 | 一個 .catch 捕捉全局 |
| 閱讀感受 | 看到頭暈 | 清晰如詩 |
3. 本日圖解心法:矮人的預約券
想像你把材料交給矮人後,他吐出一顆發光的球(Promise)。這顆球最初是灰色的(Pending)。一段時間後,如果球變綠了,它會自動呼叫你的 .then() 邏輯;如果球變紅了,它會自動跳到你的 .catch() 區塊。

⚔️ 【戰術對抗:學長與學弟的代碼對決】
招式示範:處理非同步資料
❌ 冒險學弟:地獄洋蔥 (手殘加多層巢狀)
- 負能量評級:🔴 代碼極醜 / 🔴 一個地方改錯,整棟樓垮掉
doTaskA((resultA) => {
doTaskB(resultA, (resultB) => {
doTaskC(resultB, (resultC) => {
console.log("終於完成:" + resultC);
});
});
});
✅ 勇者學長:鏈式神技 (.then 的優雅連動)
- 利潤評級:🟢 邏輯像清單一樣好懂 / 🟢 轉職高級開發者的標配
doTaskA()
.then((resultA) => doTaskB(resultA))
.then((resultB) => doTaskC(resultB))
.then((resultC) => console.log("成就達成:" + resultC))
.catch((err) => console.log("任務失敗:" + err));
🛖 【營火叮嚀:導師的經驗談】
孩子,導師當年剛學會
.then時,最常忘記寫return。如果你在
.then裡面呼叫了另一個非同步任務卻沒把結果return出去,下一個.then就會接到undefined。這就像是你在櫃檯領了第一張券,結果去下一站時把券弄丟了。記住:鏈式調用的靈魂在於「持續傳遞」。
🎓 【Phase 3 結業感言:事件大師的誕生】
恭喜你,冒險者。從 Day 15 到 Day 20,你已經掌握了:
- DOM 的操縱:看清網頁的骨架。
- 事件的律動:監聽、委派、泡泡冒泡。
- 儲存的記憶:讓網頁不再失憶 (LocalStorage)。
- 時空的隊列:理解 Event Loop,不再被非同步玩弄。
- 未來的承諾:用 Promise 優雅地捕捉異步靈魂。
這是一個巨大的分水嶺。下一個賽段,我們將開啟 Phase 4:與外部世界的連結,在那裡,你將學會如何與真正的伺服器對話。
📝 【夥伴筆記:今日修煉精華】
這份筆記是你的隨身護身符,卡關時看一眼,真相就在裡面。
- Promise 三大狀態:
- Pending (等待中):初始狀態,尚未完成亦未拒絕。
- Fulfilled (已實現):操作成功完成,透過
resolve(value)觸發.then()。 - Rejected (已拒絕):操作失敗,透過
reject(error)觸發.catch()。
- 不可逆性 (Immutability):狀態一旦從 Pending 轉為 Fulfilled 或 Rejected,便永遠鎖定,不可再次變更。
- 鏈式調用 (Chaining):在
.then()函式中回傳新的 Promise 或數值,能將資料順暢傳遞給下一層.then()。 - 統一錯誤捕捉 (Catch All):在鏈條末端加上
.catch(),即可捕捉上方任何一個節點拋出的異常。
🎯 【實戰演武場】
⚔️ 任務鑑定條件:
- 完成 📜 本日實戰任務 (CodePen)。
- 將 CodePen 網址貼至 QuestBoard,並回填鑑定報告:
- 初心者:契約發動術 (成就感發掘):
-
- 你是否成功寫出一個隨機決定「成功」或「失敗」的 Promise?
-
- 冒險者:連續任務 (理性挑戰):[⚡ 觀念辨析]
-
- 在鏈式調用中,如果第一個
.then失敗了,後面的.then還會跑嗎?(試著用.catch去抓看看!)
- 在鏈式調用中,如果第一個
-
- 初心者:契約發動術 (成就感發掘):
- 任務完成後,你的名字將永遠標記在公會的英雄榜上!
📚 【圖書館卷軸與前後站連結】
- 前導冒險: Day 00: 勇者村的入村儀式
- 上一站冒險: Day 19:原理篇 —— 為什麼程式不乖乖排隊?JS 腦袋裡的 Event Loop
- 下一站冒險: Day 21:Async / Await:用最直覺的寫法處理「還沒回來的資料」
- MDN 官方文獻: MDN 如何使用 Promise
- 視覺化複習: Promise 的三種狀態動圖