跳至主要内容

在非同步傳輸與外部 API 互動中,不可預期的網路中斷與資料異常是系統崩潰的主要殺手!本章節將手把手拆解 JavaScript 錯誤處理機制 —— try...catch...finally 的完整生命週期,傳授如何捕捉錯誤物件、主動拋出例外(throw new Error),以及運用「戰場清理術(finally)」優雅關閉 Loading 轉圈動畫,為你的程式碼穿上堅不可摧的復活保險甲。

Day 24: 錯誤處理:使用 Try...Catch 穿上你的復活保險甲

本文同步分享於2026鐵人賽:JS 核心重構:勇者轉職傳說

📜 這裡的修煉規則

孩子,在踏上今日的領地前,先坐下來喝杯酒吧。 修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。

我在每一站的盡頭都為你鋪設了 實戰演武場 CodePen。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。 成功突圍後,別忘了帶著你的戰利品回到 QuestBoard 佈告欄。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。

記住...

導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。

🛡️ 【公會大廳:導師的修煉導讀】

「導師,自從 Day 21 開始,我每次寫 async 都會乖乖照著您的吩咐,在外面套一層 try...catch。但說實話,我只是在模仿您的動作,我根本不知道那層銀色披風(復活保險甲)底層是怎麼運作的。

而且我發現,有時候即便我穿了甲,資料還是會出錯,甚至 Loading 的轉圈圈動畫會卡在那裡一輩子!我真的掌握這件裝備了嗎?」

我笑了笑,示意小冒險者脫下披風,放在工作檯上。

「孩子,模仿是學習的開始,但『理解』才是轉職的關鍵。之前你只是『穿著』它,今天我們要手把手把它『拆解』。我們要搞清楚那個名為 error 的物件裡裝了什麼情報,並且學會最重要的一招:『戰場清理術 (Finally)』,確保無論勝敗,你的程式碼都能維持工整。」


💡 【導師講義:底層真相探究】

1. 復活甲三部曲:Try, Catch, Finally

這是一套完整的生命週期,缺一不可:

  • try { ... }「勇敢嘗試」。把最可能爆炸、最危險的動作(如 Fetch 請求、JSON 解析)放進來。
  • catch (error) { ... }「落地緩衝」。如果上面的代碼炸了,這裡會立刻接住它。你可以在這顯示「網路不穩,請稍後再試」或記錄錯誤日誌。
  • finally { ... }「戰後清理」。這是最容易被忽略但最重要的。無論成功還是失敗,這裡的代碼「保證執行」

2. 實戰必殺技:Finally 的真正用途

想像你在抓資料前,畫面上顯示了一個「轉圈圈 (Loading)」動畫:

  • 如果請求成功,你要關閉轉圈圈並呈現資料。
  • 如果請求失敗,你也要關閉轉圈圈(不然使用者會在那裡看到畫面卡住等一輩子)。

這就是 finally 的舞台! 將狀態復原或關閉 Loading 放進 finally 區塊,能避免在 trycatch 兩處重複撰寫清理代碼。

3. 主動預警:throw new Error()

有時候伺服器回應了 HTTP 狀態碼但非預期,或是回傳的資料「不合業務邏輯」(例如:血量是負數)。這時你可以主動引爆炸彈,拋出例外並跳到 catch 去處理:

throw-error.js
if (data.hp < 0) {
throw new Error("勇者數值異常,包裹有毒!");
}

🛡️ 【本日圖解心法:復活甲運作圖】

🛖 營火叮嚀:導師的圖解心法

想像你在走一條獨木橋(Try)。如果你掉下去了,下面有一張厚厚的安全網(Catch)接住你,並把你送回安全區。最後,不管你有沒有掉下去,公會管理員都會過來把橋鎖上(Finally),確保下一個冒險者的安全。

復活甲原理圖


⚔️ 【戰術對抗:學長與學弟的代碼對決】

招式示範:完整的 Fetch 錯誤處理

❌ 冒險學弟:僥倖派 (只顧成功)

  • 負能量評級:🔴 斷網直接噴紅字 / 🔴 loading 轉圈圈轉到死
naive-fetch.js
async function getSupplies() {
showLoading(true);
const res = await fetch("https://api.guild.com/items"); // 如果這裡斷網,程式碼就卡死了
const data = await res.json();
showLoading(false);
}

✅ 勇者學長:穩健派 (全方位防禦)

  • 利潤評級:🟢 極致的用戶體驗 / 🟢 面試官最愛的代碼範本
safe-fetch.js
async function getSupplies() {
try {
showLoading(true);
const res = await fetch("https://api.guild.com/items");
if (!res.ok) throw new Error("領取失敗!");

const data = await res.json();
console.log("物資:", data);
} catch (err) {
showErrorMessage("📢 公會警報:" + err.message);
} finally {
// 關鍵!無論成功失敗,都要關閉轉圈圈
showLoading(false);
}
}

🛖 【營火叮嚀:導師的經驗談】

🛖 營火叮嚀:導師的經驗談

孩子,導師教你一個「職人小技巧」。

catch 裡面,不要只是單純的 console.log(error)。試著寫下有層次的訊息,例如:「[Auth Service] 失敗:無效的金鑰」。當半年後的你回頭修 Bug 時,你會感謝現在這個考慮周全的自己。

「錯誤處理不是為了隱藏問題,而是為了在問題發生時,我們依然能對系統保有控制權。」


📝 【夥伴筆記:今日修煉精華】

這份筆記是你的隨身護身符,卡關時看一眼,真相就在裡面。

  • Try 區塊保護:將任何高風險、易拋出例外的操作(如非同步請求、JSON 解析、未預期運算)放入其中進行保護。
  • Catch 緩衝攔截:當發生錯誤時立即攔截並取得 Error 物件,提供優雅的降級回饋與清晰日誌,避免整個網頁直接崩潰白屏。
  • Finally 保證執行:無論 Try 成功執行還是 Catch 攔截錯誤,Finally 區塊內的程式碼均保證觸發,是關閉 Loading 動畫、釋放資源與清理狀態的最佳場所。
  • 主動拋出例外:當商業邏輯不合規(如數值異常、業務狀態碼失敗)時,搭配 throw new Error() 主動中斷流程並轉移至 Catch 處置。

🎯 【實戰演武場】

⚔️ 任務鑑定條件:

  1. 完成 📜 本日實戰任務 (CodePen)
  2. 將 CodePen 網址貼至 QuestBoard,並回填鑑定報告:
    • 初心者:捕捉發動術 (成就感發掘)
        1. 你是否成功使用 try...catch 攔截了錯誤,而不是讓瀏覽器直接紅字噴錯?
    • 冒險者:清場大師 (理性挑戰)[⚡ 觀念辨析]
        1. 為什麼「關閉 Loading 動畫」最適合放在 finally 而不是 trycatch 裡?
        1. 故意在 try 裡面寫一段 throw new Error("自爆!"),觀察 catch 能不能領到這個訊息。
  3. 任務完成後,你的名字將永遠標記在公會的英雄榜上!

📚 【圖書館卷軸與前後站連結】