跳至主要内容

告別單機運作,正式迎向廣袤的網路世界!本章節將帶你解鎖現代前端最強大的連網利器 —— Fetch API。透過公會通訊信鴿與兩階段領包術的生動圖解,我們將深入剖析為何需要雙重 await、如何藉由 response.ok 與狀態碼建立嚴謹的防禦工事,並學會運用 Network 面板排查請求,讓你與外部伺服器的溝通暢通無阻。

Day 22: Fetch API 實戰:如何優雅地從外部搬運用資

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

📜 這裡的修煉規則

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

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

記住...

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

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

「導師,我已經學會了暫停時空的魔法(Async/Await)。但我現在身處荒野,袋子裡空空如也,我需要向遠方的王國請求後勤支援(獲取資料)。該怎麼做呢?」

我從懷中掏出一隻銀色的 「通訊信鴿 (Fetch API)」,將一張寫著網址的紙條綁在它腿上,輕輕一送,信鴿便消失在雲端。

「孩子,這就是 fetch。它是現代前端最具威力的招式之一。它能讓你跨越海洋,與全世界的伺服器對話。但要注意,拿回資料的過程就像收包裹一樣,是有層次的。今天,我們要練習如何發送這隻信鴿,並學會優雅地拆開它帶回來的神祕包裹。」


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

1. 什麼是 Fetch?(公會的跨國信鴿)

fetch() 是瀏覽器內建的原始動作,它會幫你發出網路請求。它回傳的本質依然是個 Promise,所以我們能用昨天學過的時空暫停術(Async/Await)來處理它。

2. 兩階段領包術:為什麼要兩次 Await?

這是所有新手最困惑的地方。為什麼不能一行搞定?

  1. 第一階段:等包裹送到 (Response object) 信鴿飛回來了,給了你一個箱子。這時你只知道「有沒有送到(狀態碼)」,箱子還沒打開。
  2. 第二階段:拆開包裝 (Parsing JSON) 你需要使用 .json() 這種解析咒語,強迫箱子把內容物轉換成 JavaScript 看得懂的物件。
getSupplies.js
async function getSupplies() {
// 1. 等信鴿飛回來
const response = await fetch("https://api.example.com/items");

// 2. 等拆箱完成
const data = await response.json();

console.log(data);
}

3. 防禦工事:信鴿也會迷路 (response.ok)

⚠️ 導師的警告:信鴿也會迷路 (response.ok)

fetch 有個奇怪的脾氣。即便伺服器跟你說「404 找不到檔案」,它還是會認為信鴿「飛回來了」,因此不會動用 catch

你必須親自檢查 response.ok(或是看狀態碼是否為 200)。這就像是你收到了箱子,但打開前得先看看外面有沒有貼「查無此人」。


🛡️ 【本日圖解心法:兩階段領包術】

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

想像你在窗口等物資。第一眼看到飛機飛過來丟下包裹(Response),但包裹是封死的,你看不見裡面的藥水。你必須拿出「拆箱刀 (.json())」,再次等待它解開,才能真正拿到裝備。

Fetch 兩階段領包圖


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

招式示範:獲取外部任務資料

❌ 冒險學弟:盲目直衝派 (不檢查狀態碼)

  • 負能量評級:🔴 網址打錯直接爆炸 / 🔴 404 的時候還在那邊 parse JSON
naive-fetch.js
async function getData() {
const res = await fetch("https://wrong-api.com");
const data = await res.json(); // 這裡可能會報錯
console.log(data);
}

✅ 勇者學長:嚴謹偵測派 (防備 404 的高手)

  • 利潤評級:🟢 像喝水一樣穩定的代碼 / 🟢 轉職高級開發者標配
robust-fetch.js
async function getData() {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");

if (!res.ok) {
throw new Error("物資被攔截了!狀態碼:" + res.status);
}

const data = await res.json();
console.log("🏆 任務詳情:", data.title);
} catch (err) {
console.error("🌋 通訊中斷:", err.message);
}
}

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

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

孩子,未來你在實戰中,如果發現資料一直讀不出來,別急著改代碼。先去點開瀏覽器的「F12 -> Network (網路)」面板。

那裡是信鴿的飛行日誌,它會告訴你信鴿飛去了哪、對方回了什麼,甚至連字體大小都不會騙你。「學會看 Network 面板,你才真正擁有了連通世界的能力。」


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

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

  • Fetch 的 Promise 本質fetch() 會回傳 Promise 物件,可用 async / await 優雅處理。
  • 兩階段領包:第一階段 await fetch() 取得 Response 標頭與狀態,第二階段 await res.json() 將資料流解析為 JS 物件。
  • HTTP 錯誤不拋異常:即便遇到 404 或 500,fetch() 依然視為 Promise 成功,必須手動檢查 response.ok 或狀態碼。
  • Network 面板善用:開發遇阻時優先查看 DevTools Network 分頁,確認請求網址、標頭與 Payload。

🎯 【實戰演武場】

⚔️ 任務鑑定條件:

  1. 完成 📜 本日實戰任務 (CodePen)
  2. 將 CodePen 網址貼至 QuestBoard,並回填鑑定報告:
    • 初心者:信鴿召喚術 (成就感發掘)
        1. 你是否成功從 JSONPlaceholder 獲取到一筆資料並顯示在 console 中?
    • 冒險者:防禦加護 (理性挑戰)[⚡ 觀念辨析]
        1. 故意把 API 網址打錯一個字,觀察你的 try...catch 有沒有抓到錯誤。
        1. 為什麼我們不能直接 console.log(res) 就看到資料,一定要經過 .json() 呢?
  3. 任務完成後,你的名字將永遠標記在公會的英雄榜上!

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