JavaScript Promise 完全指南:從基礎到進階
一、Promise 構造函數基礎
1.1 基本語法結構
var my_promise = new Promise(function(resolve, reject) {
// 執行器函數
if (條件) {
resolve('成功值');
} else {
reject('失敗值');
}
});
1.2 執行器函數(Executor Function)
function(resolve, reject)是匿名函數,也稱為執行器函數- 該函數有兩個參數:
resolve和reject - ⚡ 關鍵特性:執行器函數在
new Promise()時立即同步執行
1.3 resolve 和 reject 參數詳解
- 本質:
resolve和reject是函數參數(不是屬性或方法) - 來源:由 JavaScript 引擎自動創建並傳遞給執行器函數
-
作用:
resolve(value):將 Promise 狀態改為fulfilled,並傳遞成功值reject(reason):將 Promise 狀態改為rejected,並傳遞失敗原因
二、Promise 的三種狀態
| 狀態 | 英文名 | 説明 |
|---|---|---|
| 等待中 | pending |
Promise 的初始狀態 |
| 已成功 | fulfilled |
調用 resolve() 後的狀態 |
| 已失敗 | rejected |
調用 reject() 後的狀態 |
⚠️ 注意:Promise 狀態一旦改變(從 pending 到 fulfilled 或 rejected),就不可逆轉。
三、return 語句的重要性
3.1 為什麼需要 return
function createPromise() {
return new Promise((resolve, reject) => {
// 執行器函數內容
});
}
- ✅ 必須寫 return:將創建的 Promise 對象返回給外部
- ❌ 不寫 return:Promise 內部邏輯仍然執行,但外部無法獲得 Promise 對象
- 🚫 結果:無法調用
.then()和.catch()方法
3.2 執行時機説明
my_obj = createPromise(); // 此時執行器函數立即執行
- 執行器函數在
new Promise()時立即執行(同步) - 不需要調用
my_obj()來觸發執行器函數 - Promise 對象創建完成後返回給
my_obj
四、then 方法詳解
4.1 基本用法
obj.then(result => console.log(result))
4.2 語法分析
then()方法接受一個函數作為參數-
result => console.log(result)是箭頭函數(匿名函數)- 參數:
result - 函數體:
console.log(result)
- 參數:
4.3 工作原理
- Promise 狀態變為
fulfilled then方法檢測到狀態變化- 自動調用傳入的回調函數
- 將 Promise 的成功值作為參數傳遞給回調函數
4.4 等價寫法
// 箭頭函數
obj.then(result => console.log(result))
// 傳統函數
obj.then(function(result) {
console.log(result);
})
// 命名函數
function handleResult(result) {
console.log(result);
}
obj.then(handleResult)
五、Promise 靜態方法
5.1 構造函數 vs 靜態方法對比
| 方法 | 是否有執行器函數 | 用途 |
|---|---|---|
new Promise() |
✅ 有 | 創建可控制狀態的 Promise |
Promise.resolve() |
❌ 沒有 | 直接創建成功狀態的 Promise |
Promise.reject() |
❌ 沒有 | 直接創建失敗狀態的 Promise |
5.2 靜態方法列表
單個 Promise 創建
Promise.resolve(value):直接創建fulfilled狀態的 PromisePromise.reject(reason):直接創建rejected狀態的 Promise
多個 Promise 處理
Promise.all([p1, p2, p3]):等待所有成功,任一失敗則整體失敗Promise.race([p1, p2, p3]):返回最先完成的 Promise 結果Promise.any([p1, p2, p3]):等待第一個成功,全部失敗才整體失敗Promise.allSettled([p1, p2, p3]):等待所有完成,返回所有結果
5.3 靜態方法存在的意義
簡化常見操作
// 繁瑣寫法
new Promise(resolve => resolve('緩存數據'));
// 簡潔寫法
Promise.resolve('緩存數據');
解決複雜異步協調
- 併發控制:
all,race,any,allSettled - 超時處理:
race配合setTimeout - 容錯機制:
any提供多個備選方案 - 批量處理:
allSettled處理批量操作結果
六、完整示例分析
function simple_promise() {
var my_promise = new Promise(function(resolve, reject) {
run_result = true;
if (run_result) {
resolve('運行成功');
} else {
reject('運行失敗');
}
});
return my_promise;
}
obj = simple_promise();
obj.then(result => console.log(result))
.catch(reject => console.log(reject));
執行流程
- 調用
simple_promise()函數 - 執行
new Promise(),執行器函數立即運行 - 條件判斷,調用
resolve('運行成功') - Promise 狀態變為
fulfilled - 返回 Promise 對象給
obj .then()註冊成功回調函數- 由於 Promise 已經是成功狀態,立即執行回調
- 輸出:
運行成功
七、關鍵理解要點
📌 核心概念
- 執行器函數是匿名函數,在 Promise 創建時立即執行
- resolve/reject 是函數參數,由 JS 引擎提供,用於改變 Promise 狀態
- resolve() 的參數不是返回值,而是傳遞給
.then()的值 - return 必不可少,用於將 Promise 對象暴露給外部
- 靜態方法簡化操作,解決複雜異步場景的協調問題
- then 方法註冊回調,Promise 狀態改變時自動執行
🎯 最佳實踐
// ✅ 推薦寫法:清晰的錯誤處理
function fetchData() {
return new Promise((resolve, reject) => {
// 異步操作
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve({ data: '數據' });
} else {
reject(new Error('獲取失敗'));
}
}, 1000);
});
}
// 鏈式調用
fetchData()
.then(result => {
console.log('成功:', result);
return result.data;
})
.catch(error => {
console.error('失敗:', error.message);
})
.finally(() => {
console.log('操作完成');
});
八、常見誤區與陷阱
❌ 錯誤示例 1:忘記 return
function bad_promise() {
new Promise((resolve, reject) => {
resolve('數據');
});
// 忘記 return,外部無法獲取 Promise
}
bad_promise().then(data => console.log(data)); // TypeError
❌ 錯誤示例 2:誤解 resolve() 為返回值
function bad_example() {
return new Promise((resolve, reject) => {
const result = resolve('值'); // resolve 沒有返回值
console.log(result); // undefined
});
}
✅ 正確理解
resolve()只是改變狀態並傳遞值給.then()- 不要將
resolve()當作return使用
九、進階應用場景
場景 1:併發請求控制
const promises = [
fetch('/api/user'),
fetch('/api/posts'),
fetch('/api/comments')
];
Promise.all(promises)
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log('所有數據:', data))
.catch(error => console.error('某個請求失敗:', error));
場景 2:超時控制
function timeoutPromise(promise, timeout) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('超時')), timeout)
)
]);
}
timeoutPromise(fetch('/api/data'), 3000)
.then(data => console.log(data))
.catch(error => console.error(error.message));
場景 3:容錯處理
const servers = [
fetch('https://server1.com/api'),
fetch('https://server2.com/api'),
fetch('https://server3.com/api')
];
Promise.any(servers)
.then(response => console.log('第一個成功的服務器響應:', response))
.catch(error => console.error('所有服務器都失敗了'));
十、總結
Promise 是 JavaScript 異步編程的核心機制,掌握以下要點:
✅ 理解執行器函數的立即執行特性
✅ 掌握 resolve/reject 的參數傳遞機制
✅ 熟練使用 .then()/.catch()/.finally() 鏈式調用
✅ 善用靜態方法處理複雜異步場景
✅ 注意錯誤處理和狀態管理
💡 提示:Promise 是 async/await 的基礎,深入理解 Promise 有助於更好地使用現代異步語法。
參考資源:
- MDN - Promise
- [JavaScript.info - Promise](https://zh.javascript.info/promise-basics