Skip to content

Promise

Promise 是 JavaScript 中处理异步操作的一种方式。它代表一个异步操作的最终完成(或失败)及其结果值。

基本概念

1. Promise 状态

Promise 有三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)
javascript
// 创建一个 Promise
const promise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve('操作成功');
        } else {
            reject('操作失败');
        }
    }, 1000);
});

// 处理 Promise
promise
    .then(result => console.log(result))
    .catch(error => console.error(error));

2. Promise 链式调用

javascript
const fetchData = () => {
    return new Promise((resolve) => {
        setTimeout(() => resolve('数据'), 1000);
    });
};

fetchData()
    .then(data => data.toUpperCase())
    .then(data => console.log(data))
    .catch(error => console.error(error));

Promise 方法

1. Promise.all()

等待所有 Promise 完成,返回结果数组。

javascript
const promises = [
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3)
];

Promise.all(promises)
    .then(results => console.log(results)); // [1, 2, 3]

2. Promise.race()

返回第一个完成的 Promise 的结果。

javascript
const promises = [
    new Promise(resolve => setTimeout(() => resolve('快'), 100)),
    new Promise(resolve => setTimeout(() => resolve('慢'), 500))
];

Promise.race(promises)
    .then(result => console.log(result)); // '快'

3. Promise.allSettled()

等待所有 Promise 完成,返回每个 Promise 的状态和结果。

javascript
const promises = [
    Promise.resolve(1),
    Promise.reject('错误'),
    Promise.resolve(3)
];

Promise.allSettled(promises)
    .then(results => console.log(results));
// [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: '错误' },
//   { status: 'fulfilled', value: 3 }
// ]

4. Promise.any()

返回第一个成功的 Promise 的结果。

javascript
const promises = [
    Promise.reject('错误1'),
    Promise.resolve('成功'),
    Promise.reject('错误2')
];

Promise.any(promises)
    .then(result => console.log(result)); // '成功'

错误处理

1. 使用 catch

javascript
fetchData()
    .then(data => {
        throw new Error('处理错误');
    })
    .catch(error => console.error(error));

2. 使用 finally

javascript
fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error))
    .finally(() => console.log('完成'));

Promise 最佳实践

1. 避免 Promise 嵌套

javascript
// 不好的做法
fetchData()
    .then(data => {
        return fetchMoreData(data)
            .then(moreData => {
                return processData(moreData);
            });
    });

// 好的做法
fetchData()
    .then(data => fetchMoreData(data))
    .then(moreData => processData(moreData));

2. 错误处理

javascript
// 不好的做法
fetchData()
    .then(data => {
        if (!data) {
            throw new Error('没有数据');
        }
        return data;
    });

// 好的做法
fetchData()
    .then(data => {
        if (!data) {
            return Promise.reject(new Error('没有数据'));
        }
        return data;
    });

3. Promise 超时处理

javascript
const timeout = (ms) => new Promise((_, reject) => {
    setTimeout(() => reject(new Error('超时')), ms);
});

Promise.race([
    fetchData(),
    timeout(5000)
])
    .then(data => console.log(data))
    .catch(error => console.error(error));

常见陷阱

1. Promise 构造函数中的错误

javascript
// 错误会被自动捕获
new Promise((resolve, reject) => {
    throw new Error('错误');
}).catch(error => console.error(error));

2. 异步错误处理

javascript
// 异步错误需要显式处理
new Promise((resolve) => {
    setTimeout(() => {
        throw new Error('异步错误');
    }, 1000);
}).catch(error => console.error(error)); // 不会捕获异步错误

3. Promise 链中的错误传播

javascript
fetchData()
    .then(data => {
        throw new Error('错误');
    })
    .catch(error => {
        console.error(error);
        return '默认值';
    })
    .then(result => console.log(result));

性能考虑

1. Promise 创建开销

javascript
// 避免不必要的 Promise 创建
const data = '同步数据';
// 不好的做法
Promise.resolve(data).then(console.log);
// 好的做法
console.log(data);

2. 并行执行

javascript
// 使用 Promise.all 并行执行
const promises = [
    fetchData1(),
    fetchData2(),
    fetchData3()
];

Promise.all(promises)
    .then(([data1, data2, data3]) => {
        console.log(data1, data2, data3);
    });

总结

  1. Promise 提供了优雅的异步处理方式
  2. 使用链式调用避免回调地狱
  3. 合理使用 Promise 方法(all、race、allSettled、any)
  4. 正确处理错误和异常情况
  5. 注意性能优化和最佳实践
  6. 避免常见陷阱和错误