切换主题
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);
});
总结
- Promise 提供了优雅的异步处理方式
- 使用链式调用避免回调地狱
- 合理使用 Promise 方法(all、race、allSettled、any)
- 正确处理错误和异常情况
- 注意性能优化和最佳实践
- 避免常见陷阱和错误