Promise
Promise
Promise 概述
Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个未来某个事件(通常是一个异步操作)最终完成或失败的状态。通过使用 Promise,可以优化回调函数的嵌套结构,使异步流程更加清晰和可维护,并提供了错误处理机制。
1. 基本概念
定义
- Promise 是一个表示未来某个事件(通常是一个异步操作)最终完成或失败的对象。
特点
- 状态:一旦状态改变,就不会再变。Promise 对象的状态有以下三种:
- Pending(待定):初始状态,既未完成也未失败。
- Fulfilled(已完成):操作成功完成。
- Rejected(已失败):操作失败。
- 状态只能从
pending
变为fulfilled
或rejected
。
核心作用
- 优化回调函数的嵌套结构:避免“回调地狱”问题。
- 使异步流程更清晰和可维护:通过链式调用实现异步代码的顺序执行。
- 提供错误处理机制:统一管理异步操作中的错误。
2. Promise 的语法
2.1 创建一个 Promise
1
2
3
4
5
6
7const promise = new Promise((resolve, reject) => {
if (/* 成功条件 */) {
resolve("成功的结果");
} else {
reject("失败的原因");
}
});2.2 基本使用
1
2
3
4
5
6
7promise
.then(result => {
console.log("成功:", result);
})
.catch(error => {
console.error("失败:", error);
});2.3 方法链
1
2
3
4
5
6
7
8
9
10
11promise
.then(result => {
console.log("第一步成功:", result);
return "下一步的结果";
})
.then(nextResult => {
console.log("第二步成功:", nextResult);
})
.catch(error => {
console.error("发生错误:", error);
});3. Promise 的方法
3.1 静态方法
**Promise.resolve(value)**:创建一个状态为已完成(fulfilled)的 Promise。
1
2const p = Promise.resolve(42);
p.then(value => console.log(value)); // 输出: 42**Promise.reject(reason)**:创建一个状态为已失败(rejected)的 Promise。
1
2const p = Promise.reject("错误信息");
p.catch(error => console.log(error)); // 输出: 错误信息**Promise.all(iterable)**:等待所有 Promise 完成,如果有一个失败,则返回失败。
1
2const promises = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];
Promise.all(promises).then(results => console.log(results)); // 输出: [1, 2, 3]**Promise.allSettled(iterable)**:等待所有 Promise 都有结果(无论成功或失败)。
1
2
3
4
5
6const promises = [
Promise.resolve(1),
Promise.reject("失败"),
Promise.resolve(3)
];
Promise.allSettled(promises).then(results => console.log(results));**Promise.race(iterable)**:返回第一个完成的 Promise(无论成功或失败)。
1
2
3
4
5const promises = [
new Promise(resolve => setTimeout(() => resolve("快"), 100)),
new Promise(resolve => setTimeout(() => resolve("慢"), 200))
];
Promise.race(promises).then(result => console.log(result)); // 输出: 快**Promise.any(iterable)**:返回第一个成功的 Promise,如果全失败则返回 AggregateError。
1
2
3
4
5
6const promises = [
Promise.reject("失败1"),
Promise.reject("失败2"),
Promise.resolve("成功")
];
Promise.any(promises).then(result => console.log(result)); // 输出: 成功
4. Promise 的链式调用
每个
.then()
或.catch()
都会返回一个新的 Promise。可以通过链式调用来组织多个异步操作。4.1 链式结构的简单例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14new Promise((resolve, reject) => {
setTimeout(() => resolve("第一步完成"), 1000);
})
.then(result => {
console.log(result);
return "第二步完成";
})
.then(result => {
console.log(result);
throw new Error("第三步出错");
})
.catch(error => {
console.error("捕获错误:", error);
});5. 错误处理
使用
.catch()
捕获错误1
2
3
4
5
6new Promise((resolve, reject) => {
reject("失败的原因");
})
.catch(error => {
console.error("捕获错误:", error);
});在
.then()
的第二个参数中处理错误1
2
3
4
5
6new Promise((resolve, reject) => {
reject("失败的原因");
}).then(
result => console.log("成功:", result),
error => console.error("捕获错误:", error)
);使用
.finally()
方法1
2
3
4
5new Promise((resolve, reject) => {
resolve("成功");
})
.finally(() => console.log("操作结束"))
.then(result => console.log(result));
6. Promise 的内部运行原理
构造函数立即执行:Promise 的回调函数在实例化时会立即执行,异步逻辑需要手动指定。
1
2
3
4const p = new Promise((resolve, reject) => {
console.log("Promise 执行了");
resolve("完成");
});微任务队列(Microtask Queue):
then
、catch
和finally
的回调函数会在当前事件循环结束后立即执行(微任务优先于宏任务)。1
2
3
4console.log("脚本开始");
Promise.resolve().then(() => console.log("Promise 的 then"));
console.log("脚本结束");
// 输出顺序:脚本开始 -> 脚本结束 -> Promise 的 then
7. 常见使用场景
AJAX 请求
1
2
3
4
5
6
7
8
9
10
11
12function fetchData(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => (xhr.status === 200 ? resolve(xhr.response) : reject(xhr.statusText));
xhr.onerror = () => reject("网络错误");
xhr.send();
});
}
fetchData("https://api.example.com/data")
.then(data => console.log("数据:", data))
.catch(error => console.error("错误:", error));延迟执行
1
2
3
4function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
delay(1000).then(() => console.log("延迟1秒后执行"));任务队列
1
2
3
4
5
6
7
8
9
10
11
12function task1() {
return new Promise(resolve => setTimeout(() => resolve("任务1完成"), 1000));
}
function task2() {
return new Promise(resolve => setTimeout(() => resolve("任务2完成"), 2000));
}
task1()
.then(result => {
console.log(result);
return task2();
})
.then(result => console.log(result));
8. 常见问题与注意事项
- 回调函数未处理错误:必须始终在链的末尾添加
.catch()
来处理错误。 - Promise 嵌套:尽量避免 Promise 嵌套,保持链式结构的清晰性。
- Promise 状态不可逆:一旦状态变为
fulfilled
或rejected
,就不可再更改。
通过理解和应用这些概念和方法,你可以更好地利用 Promise 来编写高效且易于维护的异步代码。此外,结合
async
/await
语法糖,可以使基于 Promise 的异步编程变得更加直观和简洁。