Promise是异步编程的一种解决方案。
// Promise代表一个异步操作的最终结果
// 三种状态:pending、fulfilled、rejected
const promise = new Promise(function(resolve, reject) {
// 异步操作
setTimeout(function() {
const success = true;
if (success) {
resolve("操作成功"); // 状态变为fulfilled
} else {
reject("操作失败"); // 状态变为rejected
}
}, 1000);
});
console.log(promise); // Promise { <pending> }
// Promise有三种状态
// 1. pending: 初始状态,既不是成功也不是失败
// 2. fulfilled: 操作成功完成
// 3. rejected: 操作失败
// 状态只能改变一次
const p1 = new Promise(function(resolve, reject) {
resolve("成功");
reject("失败"); // 无效,状态已改变
});
// 状态不可逆
const p2 = new Promise(function(resolve, reject) {
resolve("第一次");
resolve("第二次"); // 无效
});
创建Promise实例的方法。
// 基本创建
const promise = new Promise(function(resolve, reject) {
// 执行异步操作
fetch("/api/data")
.then(response => response.json())
.then(data => resolve(data))
.catch(error => reject(error));
});
// 简化版
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve(random);
} else {
reject(new Error("随机数太小"));
}
}, 1000);
});
// 创建已解决的Promise
const p1 = Promise.resolve("成功");
p1.then(value => console.log(value)); // "成功"
// 等价于
const p2 = new Promise(resolve => resolve("成功"));
// 传递Promise会原样返回
const p3 = Promise.resolve(p1);
console.log(p1 === p3); // true
// 传递thenable对象
const thenable = {
then(resolve) {
resolve("thenable");
}
};
const p4 = Promise.resolve(thenable);
p4.then(value => console.log(value)); // "thenable"
// 创建已拒绝的Promise
const p1 = Promise.reject("失败");
p1.catch(reason => console.log(reason)); // "失败"
// 等价于
const p2 = new Promise((_, reject) => reject("失败"));
// 注意:reject不会解析Promise
const p3 = Promise.reject(Promise.resolve("成功"));
p3.catch(reason => console.log(reason)); // Promise { "成功" }
处理Promise成功的结果。
const promise = Promise.resolve("东巴文");
promise.then(function(value) {
console.log(value); // "东巴文"
});
// then返回新的Promise
const p1 = Promise.resolve(1);
const p2 = p1.then(value => value + 1);
const p3 = p2.then(value => value * 2);
p3.then(value => console.log(value)); // 4
// then返回新Promise,支持链式调用
fetch("/api/user/1")
.then(response => response.json())
.then(user => fetch(`/api/posts/${user.id}`))
.then(response => response.json())
.then(posts => console.log(posts))
.catch(error => console.error(error));
// 返回值会自动包装成Promise
Promise.resolve(1)
.then(value => value + 1) // 返回2
.then(value => value * 2) // 返回4
.then(value => {
console.log(value); // 4
return value + 1;
})
.then(value => console.log(value)); // 5
// then回调返回Promise
Promise.resolve(1)
.then(value => {
return new Promise(resolve => {
setTimeout(() => resolve(value * 2), 1000);
});
})
.then(value => {
console.log(value); // 2(等待1秒后输出)
return value + 1;
})
.then(value => console.log(value)); // 3
处理Promise失败的情况。
const promise = Promise.reject(new Error("出错了"));
promise.catch(function(error) {
console.error(error.message); // "出错了"
});
// 等价于then的第二个参数
promise.then(
null,
function(error) {
console.error(error);
}
);
// 错误会沿着链向下传递
Promise.resolve()
.then(() => {
throw new Error("第一步出错");
})
.then(() => {
console.log("不会执行");
})
.then(() => {
console.log("不会执行");
})
.catch(error => {
console.error(error.message); // "第一步出错"
});
// catch后可以继续then
Promise.reject("错误")
.catch(error => {
console.log("捕获:", error);
return "恢复";
})
.then(value => {
console.log("继续:", value); // "继续: 恢复"
});
// catch后再次抛出错误
Promise.reject("错误1")
.catch(error => {
console.log("捕获:", error);
throw new Error("错误2");
})
.catch(error => {
console.log("再次捕获:", error.message); // "错误2"
});
无论成功失败都会执行。
const promise = fetch("/api/data");
promise
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))
.finally(() => {
console.log("请求完成");
// 隐藏加载动画
hideLoading();
});
// finally不接收参数
Promise.resolve("成功")
.finally(() => {
console.log("清理");
})
.then(value => {
console.log(value); // "成功"
});
// finally返回值会被忽略
Promise.resolve(1)
.finally(() => 2)
.then(value => console.log(value)); // 1
// finally抛出的错误会传递
Promise.resolve(1)
.finally(() => {
throw new Error("finally错误");
})
.catch(error => console.log(error.message)); // "finally错误"
多个Promise按顺序执行。
// then返回新的Promise
const p1 = Promise.resolve(1);
const p2 = p1.then(value => {
console.log("p1:", value);
return value + 1;
});
const p3 = p2.then(value => {
console.log("p2:", value);
return value + 1;
});
p3.then(value => {
console.log("p3:", value);
});
// 输出:
// p1: 1
// p2: 2
// p3: 3
// 用户登录流程
function login(username, password) {
return fetch("/api/login", {
method: "POST",
body: JSON.stringify({ username, password })
})
.then(response => response.json())
.then(data => {
if (!data.success) {
throw new Error(data.message);
}
return data.token;
});
}
function getUserInfo(token) {
return fetch("/api/user", {
headers: { Authorization: `Bearer ${token}` }
})
.then(response => response.json());
}
function getOrders(userId) {
return fetch(`/api/orders/${userId}`)
.then(response => response.json());
}
// 链式调用
login("东巴文", "password")
.then(token => {
localStorage.setItem("token", token);
return getUserInfo(token);
})
.then(user => {
console.log("用户:", user);
return getOrders(user.id);
})
.then(orders => {
console.log("订单:", orders);
})
.catch(error => {
console.error("错误:", error);
});
并行执行多个Promise。
// 所有Promise都成功才成功
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(values => {
console.log(values); // [1, 2, 3]
});
// 一个失败就失败
const p4 = Promise.reject("错误");
Promise.all([p1, p2, p4])
.then(values => {
console.log("不会执行");
})
.catch(error => {
console.error(error); // "错误"
});
// 并行请求多个接口
function loadPageData() {
return Promise.all([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/comments").then(r => r.json())
]);
}
loadPageData()
.then(([user, posts, comments]) => {
console.log("用户:", user);
console.log("文章:", posts);
console.log("评论:", comments);
})
.catch(error => {
console.error("加载失败:", error);
});
// 带超时的请求
function fetchWithTimeout(url, timeout = 5000) {
return Promise.race([
fetch(url),
new Promise((_, reject) => {
setTimeout(() => reject(new Error("请求超时")), timeout);
})
]);
}
返回最先完成的Promise。
// 返回最先改变状态的Promise
const p1 = new Promise(resolve => {
setTimeout(() => resolve("慢"), 3000);
});
const p2 = new Promise(resolve => {
setTimeout(() => resolve("快"), 1000);
});
Promise.race([p1, p2])
.then(value => {
console.log(value); // "快"
});
function fetchWithTimeout(url, timeout = 5000) {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("请求超时")), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
}
fetchWithTimeout("/api/data", 3000)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
等待所有Promise完成(无论成功失败)。
const p1 = Promise.resolve("成功");
const p2 = Promise.reject("失败");
const p3 = Promise.resolve("成功2");
Promise.allSettled([p1, p2, p3])
.then(results => {
console.log(results);
// [
// { status: "fulfilled", value: "成功" },
// { status: "rejected", reason: "失败" },
// { status: "fulfilled", value: "成功2" }
// ]
});
Promise.allSettled([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json())
])
.then(results => {
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(`请求${index}成功:`, result.value);
} else {
console.error(`请求${index}失败:`, result.reason);
}
});
});
返回第一个成功的Promise。
const p1 = Promise.reject("错误1");
const p2 = new Promise(resolve => {
setTimeout(() => resolve("成功"), 1000);
});
const p3 = Promise.reject("错误2");
Promise.any([p1, p2, p3])
.then(value => {
console.log(value); // "成功"
})
.catch(error => {
console.error(error); // AggregateError
});
// 所有都失败才会失败
Promise.any([
Promise.reject("错误1"),
Promise.reject("错误2")
])
.catch(error => {
console.error(error); // AggregateError: All promises were rejected
console.log(error.errors); // ["错误1", "错误2"]
});
掌握了Promise后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:Promise是现代JavaScript异步编程的核心,掌握Promise的创建、链式调用和组合方法,可以优雅地处理复杂的异步流程。在 db-w.cn,我们帮你彻底理解Promise!