回调函数虽然能实现异步,但一旦遇到多个有依赖的异步任务,就会变成嵌套多层的回调地狱,代码难读、难维护、难调试。
Promise 就是为了解决这个问题而生的。它不是新的异步功能,而是异步代码的管理方案,让异步代码可以像同步代码一样链式书写。
一、Promise 是什么?
一句话:Promise 是一个表示异步操作最终完成(或失败)的对象,它让你能把回调写法改成链式调用写法,彻底告别回调地狱。
它有三种状态:
- pending:等待中(初始状态)
- fulfilled:已成功(操作完成)
- rejected:已失败(操作出错)
特点:
- 状态一旦改变,就凝固不变
- 从 pending → fulfilled 或 pending → rejected
- 改变后不可再修改
二、Promise 基本用法
1. 创建 Promise
javascript
运行
javascript
const p = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
// 成功
resolve("数据拿到了");
// 失败
// reject("请求失败");
}, 1000);
});
2. 使用 then 接收结果
javascript
运行
javascript
p.then(res => {
console.log("成功:", res);
}).catch(err => {
console.log("失败:", err);
});
3. 封装一个异步请求(模拟接口)
javascript
运行
javascript
function request(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url) {
resolve({ data: "用户数据", code: 200 });
} else {
reject("url 不能为空");
}
}, 1000);
});
}
// 使用
request("/api/user")
.then(res => console.log(res))
.catch(err => console.log(err));
三、Promise 链式调用(核心:解决回调地狱)
这是 Promise 最强大的地方:then 可以返回新 Promise,继续 then。
对比回调地狱:
javascript
运行
javascript
// 以前回调地狱
getID(function (id) {
getUser(id, function (user) {
getOrder(user, function (order) {
console.log(order);
});
});
});
Promise 链式写法:
javascript
运行
javascript
request("/id")
.then(id => request("/user/" + id))
.then(user => request("/order/" + user.id))
.then(order => console.log(order))
.catch(err => console.log("出错:", err));
清爽、线性、可维护!
四、Promise 常用 API
1. Promise.then()
成功时执行,可返回新 Promise 继续链式。
2. Promise.catch()
捕获任何环节的错误。
3. Promise.finally()
无论成功失败,一定执行(常用于关闭加载)。
javascript
运行
javascript
request("/api")
.then(res => {})
.catch(err => {})
.finally(() => {
console.log("结束");
});
4. Promise.all()
多个请求并行,全部成功才成功。
javascript
运行
javascript
const p1 = request("/api1");
const p2 = request("/api2");
Promise.all([p1, p2])
.then(res => console.log(res[0], res[1]))
.catch(err => console.log("有一个失败就失败"));
5. Promise.race()
谁先完成就用谁(不管成功失败)。
javascript
运行
javascript
Promise.race([p1, p2]).then(res => console.log("最快的结果"));
6. Promise.resolve() / Promise.reject()
快速返回成功 / 失败的 Promise。
javascript
运行
javascript
Promise.resolve(123).then(res => console.log(res));
五、Promise 手写小案例(模拟真实接口)
javascript
运行
javascript
// 模拟获取用户ID
function getUserId() {
return new Promise(resolve => {
setTimeout(() => resolve(1001), 1000);
});
}
// 模拟获取用户信息
function getUserInfo(id) {
return new Promise(resolve => {
setTimeout(() => resolve({ id, name: "张三" }), 1000);
});
}
// 模拟获取订单
function getOrder(user) {
return new Promise(resolve => {
setTimeout(() => resolve({ orderId: 1, userId: user.id }), 1000);
});
}
// 链式调用(完全没有嵌套)
getUserId()
.then(id => getUserInfo(id))
.then(user => getOrder(user))
.then(order => console.log("最终订单:", order));
六、常见面试题
1. Promise 有哪几种状态?
pending、fulfilled、rejected。
2. Promise 解决了什么问题?
回调地狱,让异步代码可链式、可阅读、可维护。
3. then、catch、finally 的执行顺序?
- 成功:then → finally
- 失败:catch → finally
- finally 一定执行
4. Promise.all 和 Promise.race 区别?
- all:全部成功才成功
- race:谁快返回谁
5. Promise 是异步还是同步?
Promise 本身是同步执行 的,then/catch/finally 是微任务异步。
七、总结
- Promise 是异步封装对象,解决回调地狱
- 状态:pending → fulfilled /rejected
- 核心写法:
new Promise((resolve,reject)=>{}) - 链式:
.then().catch().finally() - 并行:
Promise.all()、Promise.race()
Promise 是现代 JS 异步的基石,下一篇我们学习 async/await ------ Promise 的语法糖,让异步代码写得和同步一模一样。