在撰寫 JavaScript 的非同步程式時,我們通常有兩種主流方式來處理 Promise 的結果:
- 使用
.then()
搭配.catch()
- 使用
async/await
搭配try/catch
那麼問題來了:
當你要拿一個 Promise 的結果做後續處理時,該用哪一種方式?
這篇文章會帶你比較兩者的差異、優缺點,並給出實務上的建議。
🔁 基本寫法比較
使用 .then()
fetchData()
.then(data => {
console.log("資料取得成功:", data);
})
.catch(err => {
console.error("發生錯誤:", err);
});
使用 await
async function main() {
try {
const data = await fetchData();
console.log("資料取得成功:", data);
} catch (err) {
console.error("發生錯誤:", err);
}
}
main();
✅ 各自的優缺點
項目 | .then() | async/await |
---|---|---|
可讀性 | 多層 .then() 可能會變難讀 |
結構接近同步邏輯,可讀性高 |
錯誤處理 | 使用 .catch() |
可使用 try/catch 處理錯誤 |
控制流程 | 條件判斷或迴圈處理不直觀 | if 、for 等控制流可自然搭配使用 |
使用場景 | 非 async 環境(如模組頂層)適用 | 必須在 async 函式中使用 |
串接多個任務 | .then().then().then() 較直覺 |
多個 await 也清楚,但需搭配邏輯 |
🧠 多段傳遞差異
.then() 支援連鎖傳值
Promise.resolve(2)
.then(x => x * 3) // 傳遞 6
.then(y => y + 1) // 傳遞 7
.then(z => console.log(z)); // 印出 7
await 要自己手動接收變數
async function run() {
const x = await Promise.resolve(2);
const y = x * 3;
const z = y + 1;
console.log(z); // 印出 7
}
⚠️ 注意:.catch() 後還能繼續 .then()
你可能會以為錯誤後整個鏈就中止了,其實不是:
doSomething()
.catch(err => {
console.warn("錯誤被攔截:", err);
return "預設值";
})
.then(result => {
console.log("後續繼續執行:", result); // 收到預設值
});
若 .catch()
沒有拋出新的錯誤,Promise 鏈會繼續執行後面的 .then()
。
🎯 什麼情況用哪一個?
建議使用 async/await:
- 寫長流程邏輯時(可讀性更高)
- 有多個非同步步驟需依序處理
- 錯誤處理邏輯較複雜
建議使用 .then():
- 在模組頂層(不方便加
async
) - 想快速串接簡單處理流程
- 喜歡函式式風格或鏈式操作
✅ 結論
無論使用 .then()
還是 async/await
,它們本質上都在操作 Promise。
.then()
更像函數式管線await
更像同步的控制流.catch()
可以中斷.then()
鏈,也可以處理錯誤後繼續執行.finally()
可以寫多個,做收尾工作
建議平時盡量用 async/await
搭配 try/catch
,
除非你的環境或需求更適合 .then()
鏈式處理。
如果你想要更深入的示範(例如多個非同步任務併發、錯誤復原機制、top-level await 實務寫法),也歡迎留言或關注後續文章。
沒有留言:
張貼留言