什么是Promise?
Promise是ES6(ECMAScript 2015)引入的一种异步编程解决方案,用于处理异步操作。它代表一个尚未完成但预期将来会完成的操作及其结果值。
Promise有三种状态:
- pending:初始状态,既不是成功,也不是失败
- fulfilled:操作成功完成
- rejected:操作失败
基本用法
javascript
const promise = new Promise((resolve, reject) => {
// 异步操作
if (/* 操作成功 */) {
resolve(value); // 将Promise状态改为fulfilled
} else {
reject(error); // 将Promise状态改为rejected
}
});
promise.then(
value => { /* 处理成功结果 */ },
error => { /* 处理错误 */ }
);
Promise链式调用
Promise的强大之处在于可以链式调用:
javascript
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log(`最终结果: ${finalResult}`))
.catch(failureCallback); // 捕获前面所有错误
常见API
- Promise.resolve(value):返回一个以给定值解析后的Promise对象
- Promise.reject(reason):返回一个带有拒绝原因的Promise对象
- Promise.all(iterable):所有Promise都成功时返回结果数组,任何一个失败则立即返回失败
- Promise.race(iterable):返回第一个完成(成功或失败)的Promise的结果
- Promise.allSettled(iterable):等待所有Promise完成(无论成功或失败),返回结果数组
常见陷阱
1. 忘记返回Promise
javascript
// 错误示例
somePromise()
.then(val => {
anotherPromise(val); // 忘记return
})
.then(result => {
// result会是undefined
});
2. 错误处理不当
javascript
// 错误示例
somePromise()
.then(val => {
throw new Error('Oops');
}, err => {
// 这个错误处理函数不会捕获上面throw的错误
console.error(err);
});
// 正确做法
somePromise()
.then(val => {
throw new Error('Oops');
})
.catch(err => {
console.error(err); // 这里会捕获错误
});
3. Promise嵌套过深
javascript
// 反模式 - 回调地狱的Promise版本
firstPromise()
.then(firstResult => {
return secondPromise(firstResult)
.then(secondResult => {
return thirdPromise(secondResult)
.then(thirdResult => {
// 深层嵌套
});
});
});
// 改进方案
firstPromise()
.then(firstResult => secondPromise(firstResult))
.then(secondResult => thirdPromise(secondResult))
.then(thirdResult => {
// 扁平结构
});
4. 忽略未处理的rejection
未处理的Promise rejection可能导致难以追踪的问题。建议:
javascript
// Node.js中
process.on('unhandledRejection', (reason, promise) => {
console.log('未处理的rejection:', reason);
});
// 浏览器中
window.addEventListener('unhandledrejection', event => {
console.warn('未处理的rejection:', event.reason);
});
5. 混淆Promise和回调
javascript
// 错误示例
const promise = new Promise((resolve, reject) => {
someCallbackFunction((err, result) => {
if (err) reject(err);
else resolve(result);
});
// 忘记调用resolve/reject
});
// 正确做法
const promise = new Promise((resolve, reject) => {
someCallbackFunction((err, result) => {
if (err) reject(err);
else resolve(result);
});
});
最佳实践
- 总是返回Promise链中的结果,除非你确实想终止链
- 使用
.catch()
处理错误,而不是.then()
的第二个参数 - 保持Promise链扁平,避免嵌套
- 考虑使用
async/await
语法(ES2017)来简化Promise代码 - 总是处理可能的rejection
Promise是现代JavaScript异步编程的基石,理解其工作原理和常见陷阱对于编写健壮的异步代码至关重要。