非同步操作與 API 串接
2025年3月11日大约 3 分鐘
📌 學習目標
✅ 了解 AJAX 概念
✅ 學會 Promise 和 async/await
✅ 串接外部 API 資料
✅ 整合非同步技術開發實用功能
AJAX 概念
AJAX 代表「非同步 JavaScript 與 XML」(Asynchronous JavaScript and XML):
🔹 非同步(Asynchronous):不需等待伺服器回應就可以繼續執行其他操作
🔹 XML:早期用來傳輸數據的格式(現在大多使用 JSON)
AJAX 的工作原理:
- 使用 JavaScript 建立 XMLHttpRequest 物件或使用 fetch API 發送非同步請求到伺服器
- 伺服器處理請求
- 伺服器傳回回應
- JavaScript 處理回應並更新頁面特定部分
AJAX 的優點:
🔹 改善使用者體驗,因為頁面不需完全重新載入
🔹 減少伺服器負載,因為只傳輸需要的數據
🔹 減少網路流量,因為不需重新傳輸整個頁面
🔹 提高應用程式的回應速度和互動性
fetch()
:簡單的 AJAX 請求
🔹 使用 fetch()
取得 API 資料
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("錯誤:", error))
🎯 練習
使用 fetch()
取得 https://jsonplaceholder.typicode.com/users/1
的資料,並印出 name
。
Promise 基礎
🔹 Promise 是非同步操作的解決方案
let myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功!")
}, 2000)
})
myPromise
.then((result) => console.log(result))
.catch((error) => console.log(error))
🎯 練習
建立一個 Promise
,2 秒後回傳 "載入完成"
,並印出結果。
async/await
概念
🔹 使用 async
/ await
讓程式更直覺
async function getData() {
try {
let response = await fetch("https://jsonplaceholder.typicode.com/posts/1")
let data = await response.json()
console.log(data)
} catch (error) {
console.error("發生錯誤:", error)
}
}
getData()
🎯 練習
用 async/await
取得 https://jsonplaceholder.typicode.com/todos/1
,並印出 title
。
處理多個 API 請求
🔹 串連請求
async function getUserAndPosts() {
try {
// 先取得使用者資料
let userResponse = await fetch(
"https://jsonplaceholder.typicode.com/users/1"
)
let user = await userResponse.json()
// 再取得該使用者的貼文
let postsResponse = await fetch(
`https://jsonplaceholder.typicode.com/posts?userId=${user.id}`
)
let posts = await postsResponse.json()
console.log("使用者:", user.name)
console.log("貼文數:", posts.length)
return { user, posts }
} catch (error) {
console.error("錯誤:", error)
}
}
🔹 並行請求
async function fetchMultipleData() {
try {
let [usersResponse, postsResponse] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users"),
fetch("https://jsonplaceholder.typicode.com/posts"),
])
let users = await usersResponse.json()
let posts = await postsResponse.json()
console.log("使用者數:", users.length)
console.log("貼文數:", posts.length)
return { users, posts }
} catch (error) {
console.error("錯誤:", error)
}
}
綜合範例
💡 倒數計時器 + API 串接
- 設計一個倒數計時器,按下按鈕後開始倒數,時間歸零時,從 API 取得一條隨機訊息顯示在畫面上。
- 結合
fetch()
和setTimeout()
,讓倒數結束後顯示「今日一句話」的 API 資料。
📌 範例程式碼
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<title>倒數計時器 + API 串接</title>
<style>
#timer {
font-size: 48px;
margin: 20px 0;
}
#quote {
font-style: italic;
margin-top: 20px;
color: #333;
}
</style>
</head>
<body>
<h1>倒數完畢後顯示名言佳句</h1>
<div id="timer">10</div>
<button id="startBtn">開始倒數</button>
<div id="quote"></div>
<script>
let countdown
let seconds = 10
document
.getElementById("startBtn")
.addEventListener("click", function () {
// 重置
clearInterval(countdown)
seconds = 10
document.getElementById("timer").innerText = seconds
document.getElementById("quote").innerText = ""
// 開始計時
countdown = setInterval(function () {
seconds--
document.getElementById("timer").innerText = seconds
if (seconds <= 0) {
clearInterval(countdown)
fetchQuote()
}
}, 1000)
})
async function fetchQuote() {
try {
let response = await fetch("https://api.quotable.io/random")
let data = await response.json()
document.getElementById(
"quote"
).innerText = `"${data.content}" — ${data.author}`
} catch (error) {
document.getElementById("quote").innerText =
"無法取得名言佳句,請再試一次。"
console.error("錯誤:", error)
}
}
</script>
</body>
</html>
🎯 延伸練習
- 讓使用者可以設定倒數時間。
- 加入進度條顯示倒數進度。
- 加入暫停、繼續功能。
- 嘗試使用不同的 API 來源。