深入理解 JavaScript 的 Promise:异步编程的核心

Promise 是现代 JavaScript 异步编程的基石,它为我们提供了一种更优雅的方式来处理异步操作。理解 Promise 的工作原理对于编写可维护的异步代码至关重要。

Promise 的基本概念

Promise 是一个代表了异步操作最终完成或失败的对象。它有三种状态:

  • pending:初始状态,既不是成功,也不是失败
  • fulfilled:操作成功完成
  • rejected:操作失败
const promise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve('操作成功');
        } else {
            reject('操作失败');
        }
    }, 1000);
});

Promise 的方法链

Promise 的核心优势在于其链式调用能力,这使得异步代码可以像同步代码一样顺序执行。

then() 方法

promise
    .then(result => {
        console.log(result); // "操作成功"
        return result + "!";
    })
    .then(newResult => {
        console.log(newResult); // "操作成功!"
    });

catch() 方法

promise
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error('错误:', error); // 处理所有错误
    });

finally() 方法

promise
    .then(result => console.log(result))
    .catch(error => console.error(error))
    .finally(() => {
        console.log('无论成功失败都会执行');
    });

静态方法

Promise.all()

等待所有 promise 都成功完成,或任何一个失败。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve) => {
    setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3])
    .then(values => {
        console.log(values); // [3, 42, "foo"]
    });

Promise.race()

返回第一个敲定的 promise 的结果。

const promise1 = new Promise((resolve) => {
    setTimeout(resolve, 500, '第一个');
});

const promise2 = new Promise((resolve) => {
    setTimeout(resolve, 100, '第二个');
});

Promise.race([promise1, promise2])
    .then(value => {
        console.log(value); // "第二个"
    });

Promise.allSettled()

等待所有 promise 都被敲定(无论是成功还是失败)。

const promise1 = Promise.resolve(1);
const promise2 = Promise.reject('错误');

Promise.allSettled([promise1, promise2])
    .then(results => {
        results.forEach(result => {
            if (result.status === 'fulfilled') {
                console.log('成功:', result.value);
            } else {
                console.log('失败:', result.reason);
            }
        });
    });

错误处理模式

链式错误处理

asyncOperation()
    .then(handleSuccess)
    .catch(handleError); // 捕获前面所有 then 中的错误

每个 then 单独处理错误

asyncOperation()
    .then(handleSuccess, handleSpecificError) // 只处理当前阶段的错误
    .then(nextOperation)
    .catch(handleAllErrors); // 捕获剩余错误

实际应用场景

1. API 请求顺序执行

function fetchUserData(userId) {
    return fetch(`/api/users/${userId}`)
        .then(response => response.json())
        .then(user => {
            return fetch(`/api/posts?userId=${user.id}`);
        })
        .then(response => response.json());
}

2. 并行请求

function loadUserResources(userId) {
    return Promise.all([
        fetch(`/api/users/${userId}`).then(r => r.json()),
        fetch(`/api/posts?userId=${userId}`).then(r => r.json()),
        fetch(`/api/comments?userId=${userId}`).then(r => r.json())
    ]);
}

3. 超时控制

function withTimeout(promise, timeout) {
    return Promise.race([
        promise,
        new Promise((_, reject) => {
            setTimeout(() => reject(new Error('请求超时')), timeout);
        })
    ]);
}

最佳实践

  1. 总是返回 Promise:在 then() 回调中返回新的值或 Promise
  2. 正确处理错误:使用 catch() 或 then() 的第二个参数处理错误
  3. 避免嵌套:使用链式调用而不是嵌套 then()
  4. 使用 async/await:在支持的环境中使用更现代的语法
// 不好的做法
promise.then(result => {
    anotherPromise(result).then(anotherResult => {
        // 嵌套过深
    });
});

// 好的做法
promise
    .then(result => anotherPromise(result))
    .then(anotherResult => {
        // 清晰的链式调用
    });

Promise 为我们提供了处理异步操作的强大工具,理解其工作原理和最佳实践将显著提高异步代码的质量和可维护性。

可以加入我们的QQ技术群(651706395),互相交流!

posted @ 2025-08-26 14:14  深圳蔓延科技有限公司  阅读(15)  评论(0)    收藏  举报