本文同步分享於個人部落格:Liwen Chiou | Digital Architect & Full-Stack Engineer
孩子,在踏上今日的領地前,先坐下來喝杯酒吧。
修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。我在每一站的盡頭都為你鋪設了 「
實戰演武場 CodePen」。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。
成功突圍後,別忘了帶著你的戰利品回到 「QuestBoard 佈告欄」。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。記住...
「 導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。 」
「導師,自從 Day 21 開始,我每次寫 async 都會乖乖照著您的吩咐,在外面套一層 try...catch。但說實話,我只是在模仿您的動作,我根本不知道那層銀色披風(復活保險甲)底層是怎麼運作的。
而且我發現,有時候即便我穿了甲,資料還是會出錯,甚至 Loading 的轉圈圈動畫會卡在那裡一輩子!我真的掌握這件裝備了嗎?」
我笑了笑,示意小冒險者脫下披風,放在工作檯上。
「孩子,模仿是學習的開始,但『理解』才是轉職的關鍵。之前你只是『穿著』它,今天我們要手把手把它『拆解』。我們要搞清楚那個名為 error 的物件裡裝了什麼情報,並且學會最重要的一招:『戰場清理術 (Finally)』,確保無論勝敗,你的程式碼都能維持工整。」
這是一套完整的生命週期,缺一不可:
try { ... }:「勇敢嘗試」。把最可能爆炸、最危險的動作(如 Fetch、JSON 解析)放進來。catch (error) { ... }:「落地緩衝」。如果上面的代碼炸了,這裡會立刻接住它。你可以在這顯示「網路不穩,請稍後再試」。finally { ... }:「戰後清理」。這是最容易被忽略但最重要的。無論成功還是失敗,這裡的代碼「保證執行」。想像你在抓資料前,畫面上顯示了一個「轉圈圈 (Loading)」。
這就是 finally 的舞台!
throw new Error()有時候伺服器沒報錯,但回傳的資料「不合邏輯」(例如:血量是負數)。這時你可以主動引爆炸彈,跳到 catch 去處裡:
if (data.hp < 0) {
throw new Error("勇者數值異常,包裹有毒!");
}
導師的圖解心法: 想像你在走一條獨木橋(Try)。如果你掉下去了,下面有一張厚厚的安全網(Catch)接住你,並把你送回安全區。最後,不管你有沒有掉下去,公會管理員都會過來把橋鎖上(Finally),確保下一個冒險者的安全。

async function getSupplies() {
showLoading(true);
const res = await fetch("..."); // 如果這裡斷網,程式碼就卡死了
const data = await res.json();
showLoading(false);
}
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...catch 攔截了錯誤,而不是讓瀏覽器直接紅字噴錯?finally 而不是 try 或 catch 裡?try 裡面寫一段 throw new Error("自爆!"),觀察 catch 能不能領到這個訊息。