Promise 详解
为什么需要 Promise
在实际开发中,我们经常需要处理异步操作链。例如:
- 通过 AJAX 请求获取用户 ID
- 根据 ID 请求用户名
- 根据用户名获取邮箱地址
使用传统回调函数会导致"回调地狱"(回调函数中嵌套回调函数),而 Promise 正是为了解决这个问题而诞生的。
Promise 基本使用
语法
Promise 接受一个函数作为参数,该函数包含两个参数:
resolve: 成功回调函数reject: 失败回调函数
Promise 实例
每个 Promise 实例都有两个关键属性:
state: 表示当前状态result: 存储操作结果
Promise 的三种状态
pending(等待中)fulfilled(已成功)rejected(已失败)
状态改变方法
resolve(): 将状态改为fulfilledreject(): 将状态改为rejected
注意:Promise 的状态改变是一次性的,不可逆转。
Promise 的方法
then 方法
- 通过形参获取 Promise 对象的结果
- 返回一个新的 Promise 实例(初始状态为 pending)
- 如果 Promise 状态未改变,不会执行 then 中的方法
- 可以通过
return将返回的 Promise 实例状态改为fulfilled - 如果代码出错,返回的 Promise 实例状态会改为
rejected
catch 方法
用于捕获和处理错误
async 和 await
async 函数
- 返回值总是 Promise 对象
- 结果由函数执行的返回值决定:
- 返回非 Promise 值:成功状态
- 返回 Promise 对象:继承该 Promise 的状态
- 抛出异常:失败状态
javascript
async function main() {
// 1. 返回非 Promise 值(成功状态)
// return "字符串/数字/布尔值";
// 2. 返回 Promise 对象
return new Promise((resolve, reject) => {
resolve("OK"); // 成功状态
// reject("Err"); // 失败状态
});
// 3. 抛出异常(失败状态)
// throw "oh No";
}
await 表达式
- 右侧表达式通常是 Promise 对象
- 如果是 Promise 对象,返回其成功值
- 如果是其他值,直接返回该值
注意事项:
- await 必须用在 async 函数中
- 如果 await 的 Promise 失败,会抛出异常
- 建议使用 try...catch 捕获错误
实践示例
javascript
const fs = require("fs");
const util = require("util");
const mineReadFile = util.promisify(fs.readFile); // 转换为 Promise 形式
async function main() {
try {
let data1 = await mineReadFile("./resource/1.html");
let data2 = await mineReadFile("./resource/2.html");
let data3 = await mineReadFile("./resource/3.html");
} catch(e) {
console.log(e);
}
}