
Promise為了解決什麼問題
- JavaScript Promise是一種用來處理異步操作的對象,它代表一個異步操作的成功(resolve)或失敗(reject)的結果。(以下皆使用setTimeout()示範異步操作的案例)
- 透過這種方法能避免回調地獄(Callback Hell)的問題。
- 以下直接透過Callback Hell的函數說明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function operationA(callbackA) { setTimeout(() => { console.log("Operation A completed"); callbackA(); }, 1000); } function operationB(callbackB) { setTimeout(() => { console.log("Operation B completed"); callbackB(); }, 1500); } function operationC(callbackC) { setTimeout(() => { console.log("Operation C completed"); callbackC(); }, 2000); }
operationA(() => { operationB(() => { operationC(() => { console.log("All operations completed"); }); }); });
|
顯示如下(依序出現A->B->C->All):
1 2 3 4
| Operation A completed Operation B completed Operation C completed All operations completed
|
這邊特別強調多層次結構的Callback Hell會變成像是波動拳的結構!!!難以維護

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| function operationA() { return new Promise((resolve) => { setTimeout(() => { console.log("Operation A completed"); resolve(); }, 1000); }); } function operationB() { return new Promise((resolve) => { setTimeout(() => { console.log("Operation B completed"); resolve(); }, 1500); }); } function operationC() { return new Promise((resolve) => { setTimeout(() => { console.log("Operation C completed"); resolve(); }, 2000); }); }
operationA() .then(() => operationB()) .then(() => operationC()) .then(() => console.log("All operations completed")) .catch((error) => console.error("Error:", error));
|
顯示如下(依序出現A->B->C->All)
1 2 3 4
| Operation A completed Operation B completed Operation C completed All operations completed
|
Promise狀態
- 當你使用 Promise時,它可以處於三種不同的狀態(狀態改變後就不可逆):
- Peding(等待中)
- Fulfiled(已完成)
- 異步事件完成時,透過resolve()方法將Promise狀態改變至Fulfiled(已完成)
- 此時可以透過.then回傳Promise執行的結果
- Rejected(已拒絕)
- 異步事件失敗時,透過reject()方法將Promise狀態改變至Rejected(已失敗)
- 此時可透過.catch處理Promise的錯誤訊息
- .finally()—最終結果

1 2 3 4 5 6 7 8 9 10
| operationA() .then((res) => { console.log("操作成功:", res); }) .catch((error) => { console.error("錯誤:", error); }) .finally(() => { console.log("不論成功還是失敗都會執行的代碼"); });
|
- Fulfilled案例(如果Nb小於10代表成功)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function operationA(Number) { return new Promise((resolve, reject) => { setTimeout(() => { if (Number < 10) { resolve({ Status: "OK" }); } else { reject({ Status: "Error" }); } }, 1000); }); }
const Nb = 5 operationA(Nb) .then((res) => { console.log("異步事件-正確執行回傳資料", res) }) .catch((error) => { console.error("異步事件-異常訊息:", error) })
|
顯示如下(.then()捕獲異步事件回傳資料):
1
| 異步事件-正確執行回傳資料 { Status: 'OK' }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function operationA(Number) { return new Promise((resolve, reject) => { setTimeout(() => { if (Number < 10) { resolve({ Status: "OK" }); } else { reject({ Status: "Error" }); } }, 1000); }); }
const Nb = 20 operationA(Nb) .then((res) => { console.log("異步事件-正確執行回傳資料", res) }) .catch((error) => { console.error("異步事件-異常訊息:", error) })
|
顯示如下(透過.catch()捕獲異步事件錯誤訊息):
1
| 異步事件-異常訊息: { Status: 'Error' }
|
- Promise的鏈式調用(多個異步事件同步執行):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function operationA(Number) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ Number: Number * 2 }); }, 1000); }); }
const Nb = 20 operationA(Nb) .then((res) => { console.log("第一階段-異步事件-正確執行回傳資料", res) return operationA(res.Number) }) .then((res) => { console.log("第二階段-異步事件-正確執行回傳資料", res) }) .catch((error) => { console.error("異步事件-異常訊息:", error) })
|
顯示如下(確保第一個事件執行完接收res.Number,進行第二次異步事件):
1 2
| 第一階段-異步事件-正確執行回傳資料 { Number: 40 } 第二階段-異步事件-正確執行回傳資料 { Number: 80 }
|
Promise靜態方法
Promise.resolve(value) & Promise.reject(reason)
- Promise.resolve(value):回傳Promise已完成的結果
- Promise.reject(reason):回傳Promise被拒絕的結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Promise.resolve("Reject Result") .then((res) => { console.log("Resolved:", res); }) .catch((error) => { console.log("Rejected:", error); });
Promise.reject("Reject Result") .then((res) => { console.log("Resolved:", res); }) .catch((error) => { console.log("Rejected:", error); });
|
顯示如下:
1 2
| Resolved: Reject Result Rejected: Reject Result
|
Promise.all(iterable)
- 等待所有Promise狀態轉變成Fulfiled取得的結果,返回一個包含所有解析值的數組。
- 如果其中一個Promise狀態轉變成Rejected,整個Promise.all()都會被拒絕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function operationA() { return new Promise((resolve) => { setTimeout(() => { console.log("Operation A completed"); resolve({ Statue: "A" }); }, 1000); }); } function operationB() { return new Promise((resolve) => { setTimeout(() => { console.log("Operation B completed"); resolve({ Statue: "B" }); }, 1500); }); } Promise.all([operationA(), operationB()]) .then((res) => { console.log("res", res) }) .catch((error) => { console.error("Error", error); });
|
顯示如下:
1 2 3
| Operation A completed Operation B completed res [ { Statue: 'A' }, { Statue: 'B' } ]
|
Promise.race(iterable)
- 只要其中一個Promise狀態轉變成Fulfiled或Rejected立即結束,返回第一個成功(resolve)或被拒絕(reject)的Promise。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function operationA() { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ Statue: "A" }); }, 500); }); } function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => { reject({ Statue: "Timeout" }); }, ms); }); } Promise.race([operationA(), timeout(1000)]) .then((res) => { console.log("res", res) }) .catch((error) => { console.error("Error", error); });
|
顯示如下:
async/await
- 由async函數及await運算子組成,用於處理異步操作的語法糖。
- await會解析Promise中的Fulfiled完成狀態回傳值
- 將async/await用法與Promise鍊式寫法相互比較案例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| function operationA(Number) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ Number: Number * 2 }); }, 1000); }); }
async function fetchData() { try { const Nb = 20; const result1 = await operationA(Nb); console.log("第一階段-異步事件-正確執行回傳資料", result1); const result2 = await operationA(result1.Number); console.log("第二階段-異步事件-正確執行回傳資料", result2); } catch (error) { console.error("異步事件-異常訊息:", error); } }
fetchData();
|
顯示如下:
1 2
| 第一階段-異步事件-正確執行回傳資料 { Number: 40 } 第二階段-異步事件-正確執行回傳資料 { Number: 80 }
|