博客 / 詳情

返回

JavaScript Promise 詳解

JavaScript Promise 完全指南:從基礎到進階

一、Promise 構造函數基礎

1.1 基本語法結構

var my_promise = new Promise(function(resolve, reject) {
    // 執行器函數
    if (條件) {
        resolve('成功值');
    } else {
        reject('失敗值');
    }
});

1.2 執行器函數(Executor Function)

  • function(resolve, reject)匿名函數,也稱為執行器函數
  • 該函數有兩個參數:resolvereject
  • 關鍵特性:執行器函數在 new Promise()立即同步執行

1.3 resolve 和 reject 參數詳解

  • 本質resolvereject函數參數(不是屬性或方法)
  • 來源:由 JavaScript 引擎自動創建並傳遞給執行器函數
  • 作用

    • resolve(value):將 Promise 狀態改為 fulfilled,並傳遞成功值
    • reject(reason):將 Promise 狀態改為 rejected,並傳遞失敗原因

二、Promise 的三種狀態

狀態 英文名 説明
等待中 pending Promise 的初始狀態
已成功 fulfilled 調用 resolve() 後的狀態
已失敗 rejected 調用 reject() 後的狀態

⚠️ 注意:Promise 狀態一旦改變(從 pendingfulfilledrejected),就不可逆轉


三、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 工作原理

  1. Promise 狀態變為 fulfilled
  2. then 方法檢測到狀態變化
  3. 自動調用傳入的回調函數
  4. 將 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 狀態的 Promise
  • Promise.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));

執行流程

  1. 調用 simple_promise() 函數
  2. 執行 new Promise(),執行器函數立即運行
  3. 條件判斷,調用 resolve('運行成功')
  4. Promise 狀態變為 fulfilled
  5. 返回 Promise 對象給 obj
  6. .then() 註冊成功回調函數
  7. 由於 Promise 已經是成功狀態,立即執行回調
  8. 輸出運行成功

七、關鍵理解要點

📌 核心概念

  1. 執行器函數是匿名函數,在 Promise 創建時立即執行
  2. resolve/reject 是函數參數,由 JS 引擎提供,用於改變 Promise 狀態
  3. resolve() 的參數不是返回值,而是傳遞給 .then() 的值
  4. return 必不可少,用於將 Promise 對象暴露給外部
  5. 靜態方法簡化操作,解決複雜異步場景的協調問題
  6. 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
user avatar azonips314 頭像 juqipeng 頭像 kaige 頭像 u_16213335 頭像 friesonthepier 頭像
5 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.