Promise 是 JavaScript 中用于处理异步操作的核心工具。它提供了一种更优雅的方式来管理异步代码,避免了传统回调函数的嵌套问题(俗称“回调地狱”)
1. Promise 的基本概念
Promise 是一个对象,表示一个异步操作的最终状态(成功或失败),并可以通过回调函数处理结果。
Promise 的三种状态
- Pending(进行中):初始状态,异步操作尚未完成。
- Fulfilled(已完成):异步操作成功完成。
- Rejected(已失败):异步操作失败。
2. Promise 的基本用法
2.1 创建 Promise
通过 new Promise 创建一个 Promise 对象,接收一个执行器函数(executor),该函数有两个参数:resolve 和 reject。
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve("Operation succeeded!"); // 异步操作成功
} else {
reject("Operation failed!"); // 异步操作失败
}
}, 1000);
});
2.2 处理 Promise 结果
使用 .then() 处理成功结果,使用 .catch() 处理失败结果。
promise
.then((result) => {
console.log(result); // 输出:Operation succeeded!
})
.catch((error) => {
console.error(error); // 输出:Operation failed!
});
2.3 链式调用
.then() 返回一个新的 Promise,因此可以进行链式调用:
promise
.then((result) => {
console.log(result); // 输出:Operation succeeded!
return "Next step"; // 返回一个新的值
})
.then((nextResult) => {
console.log(nextResult); // 输出:Next step
})
.catch((error) => {
console.error(error);
});
3. 实现多个异步操作的顺序执行
通过链式调用 .then(),可以实现多个异步操作的顺序执行。
示例:顺序执行
function asyncTask1() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task 1 completed");
resolve("Result 1");
}, 1000);
});
}
function asyncTask2() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task 2 completed");
resolve("Result 2");
}, 1000);
});
}
function asyncTask3() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task 3 completed");
resolve("Result 3");
}, 1000);
});
}
asyncTask1()
.then((result1) => {
console.log(result1);
return asyncTask2(); // 返回下一个 Promise
})
.then((result2) => {
console.log(result2);
return asyncTask3(); // 返回下一个 Promise
})
.then((result3) => {
console.log(result3);
})
.catch((error) => {
console.error(error);
});
输出
Task 1 completed
Result 1
Task 2 completed
Result 2
Task 3 completed
Result 3
4. 实现多个异步操作的同步执行
通过 Promise.all(),可以同时执行多个异步操作,并等待所有操作完成。
示例:同步执行
Promise.all([asyncTask1(), asyncTask2(), asyncTask3()])
.then((results) => {
console.log("All tasks completed:", results); // 输出:All tasks completed: ["Result 1", "Result 2", "Result 3"]
})
.catch((error) => {
console.error("One of the tasks failed:", error);
});
注意
- 如果其中一个 Promise 失败,Promise.all() 会立即返回失败结果。
- 如果想要忽略失败,可以使用 Promise.allSettled()。
5. 其他常用方法
5.1Promise.race()
返回第一个完成的 Promise(无论成功或失败)。
Promise.race([asyncTask1(), asyncTask2(), asyncTask3()])
.then((result) => {
console.log("First task completed:", result);
})
.catch((error) => {
console.error("First task failed:", error);
});
5.2Promise.allSettled()
等待所有 Promise 完成,无论成功或失败。
Promise.allSettled([asyncTask1(), asyncTask2(), asyncTask3()])
.then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("Resolved:", result.value);
} else {
console.error("Rejected:", result.reason);
}
});
});
6. 实现同步执行
在 JavaScript 中,异步代码无法直接变成同步执行。但可以通过以下方式模拟同步执行:
6.1 使用async/await
async/await 是 ES7 引入的语法糖,可以让异步代码看起来像同步代码。
示例:顺序执行
async function runTasks() {
try {
const result1 = await asyncTask1();
console.log(result1);
const result2 = await asyncTask2();
console.log(result2);
const result3 = await asyncTask3();
console.log(result3);
} catch (error) {
console.error(error);
}
}
runTasks();
示例:同步执行
async function runAllTasks() {
try {
const results = await Promise.all([asyncTask1(), asyncTask2(), asyncTask3()]);
console.log("All tasks completed:", results);
} catch (error) {
console.error("One of the tasks failed:", error);
}
}
runAllTasks();
- Promise 是处理异步操作的核心工具,支持链式调用和错误处理。
- 通过 .then() 链式调用,可以实现多个异步操作的顺序执行。
- 通过 Promise.all(),可以实现多个异步操作的同步执行。
- async/await 是更优雅的语法糖,使异步代码看起来像同步代码。