Promise 入门:告别回调地狱的第一步
为什么 JavaScript 需要 Promise?它解决了什么问题?小明带你从回调地狱的深渊爬出来,理解 Promise 的核心概念、链式调用以及错误处理。
Promise 入门:告别回调地狱的第一步
你一定写过这样的代码:
getUser(userId, function(user) {
getOrders(user.id, function(orders) {
getOrderDetails(orders[0].id, function(details) {
console.log(details);
// 如果还有下一层呢?
});
});
});
一层套一层,越写越深,代码最终变成了一个向右倾斜的金字塔。这就是传说中的回调地狱(Callback Hell)。
今天,小明就带你认识 JavaScript 异步编程的第一个"救世主"——Promise。
一、什么是 Promise?
Promise 是一个代表异步操作最终完成或失败的对象。它就像一张"凭证",承诺你将来会得到一个结果。
一个 Promise 有三种状态:
- Pending(进行中):初始状态,操作还没完成。
- Fulfilled(已成功):操作成功完成。
- Rejected(已失败):操作失败。
一旦状态改变,就不会再变了。 这是 Promise 最重要的特性。
二、创建一个 Promise
const myPromise = new Promise((resolve, reject) => {
// 模拟一个异步操作,比如网络请求
setTimeout(() => {
const success = true;
if (success) {
resolve('操作成功!'); // 成功时调用 resolve
} else {
reject('操作失败!'); // 失败时调用 reject
}
}, 1000);
});
resolve 和 reject 是两个函数,分别用来把 Promise 的状态从 Pending 改变成 Fulfilled 或 Rejected。
三、使用 Promise:.then() 和 .catch()
创建了 Promise 之后,怎么获取它的结果呢?
myPromise
.then(result => {
console.log(result); // '操作成功!'
})
.catch(error => {
console.error(error);
});
.then()接收成功后的回调。.catch()接收失败后的回调。
四、链式调用:Promise 的精髓
这才是 Promise 真正解决回调地狱的地方。
.then() 会返回一个新的 Promise,所以你可以无限链接下去,代码不再是金字塔,而是一条直线:
getUser(userId)
.then(user => getOrders(user.id))
.then(orders => getOrderDetails(orders[0].id))
.then(details => {
console.log(details);
})
.catch(error => {
// 任何一步出错,都会在这里被捕获
console.error('出错了:', error);
});
看看这代码,是不是清爽多了?
五、Promise.all 和 Promise.race
5.1 Promise.all:全部成功才成功
当你需要同时发起多个请求,并且等所有请求都完成后再执行下一步:
Promise.all([getUser(1), getUser(2), getUser(3)])
.then(results => {
console.log(results); // [user1, user2, user3]
});
注意:只要有一个 Promise 失败,整个 Promise.all 就会立即失败。
5.2 Promise.race:谁快用谁
只取最先完成的那个结果:
Promise.race([fetchFromServer1(), fetchFromServer2()])
.then(result => {
console.log('最快的服务器返回了:', result);
});
六、常见错误
6.1 忘记 return
在 .then() 链中,如果你想把一个值传递给下一个 .then(),必须 return:
// ❌ 错误
.then(user => {
getOrders(user.id); // 忘记 return,下一个 then 收到的是 undefined
})
// ✅ 正确
.then(user => {
return getOrders(user.id);
})
6.2 不捕获错误
没有 .catch() 的 Promise 链,如果出错,错误会被静默吞掉,非常难排查。
总结
- Promise 是处理异步操作的标准方式。
- 三种状态:Pending → Fulfilled / Rejected,不可逆。
- 链式调用 (
.then().then()) 是解决回调地狱的核心。 - 错误处理:链末尾一定要加
.catch()。
小明建议:
Promise 是 async/await 的基石。如果你想写出优雅的异步代码,必须先把 Promise 吃透。不要跳过这一步直接学 async/await,那样只是"会用",而不是"理解"。
"Promise 的本质是什么?" "是对未来的承诺。成功就兑现,失败就赔偿。" —— 小明
最后,送你一个冷笑话:
Promise 问程序员:"你相信我吗?"
程序员说:"我给你加个 .catch(),如果你骗我,我就知道了。"
Promise 叹了口气:"你这不叫信任,你这叫'验证驱动开发'。"