Promise详解:从回调地狱到优雅异步

Promise 详解

为什么需要 Promise

在实际开发中,我们经常需要处理异步操作链。例如:

  1. 通过 AJAX 请求获取用户 ID
  2. 根据 ID 请求用户名
  3. 根据用户名获取邮箱地址

使用传统回调函数会导致"回调地狱"(回调函数中嵌套回调函数),而 Promise 正是为了解决这个问题而诞生的。

Promise 基本使用

语法

Promise 接受一个函数作为参数,该函数包含两个参数:

  • resolve: 成功回调函数
  • reject: 失败回调函数

Promise 实例

每个 Promise 实例都有两个关键属性:

  • state: 表示当前状态
  • result: 存储操作结果

Promise 的三种状态

  1. pending (等待中)
  2. fulfilled (已成功)
  3. rejected (已失败)

状态改变方法

  • resolve(): 将状态改为 fulfilled
  • reject(): 将状态改为 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 对象,返回其成功值
  • 如果是其他值,直接返回该值

注意事项:

  1. await 必须用在 async 函数中
  2. 如果 await 的 Promise 失败,会抛出异常
  3. 建议使用 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);
  }
}
相关推荐
0思必得022 分钟前
[Web自动化] 开发者工具控制台(Console)面板
前端·javascript·python·自动化·web自动化·开发者工具
zhixingheyi_tian23 分钟前
TestDFSIO 之 热点分析
android·java·javascript
weixin_3077791324 分钟前
Jenkins Bootstrap 5 API插件:现代化Jenkins界面的开发利器
开发语言·前端·网络·bootstrap·jenkins
小毛驴85024 分钟前
快速设置 npm 源
前端·npm·node.js
花花鱼24 分钟前
nginx 解决跨域问题
前端·javascript·nginx
步步为营DotNet25 分钟前
深入解读CancellationToken:.NET异步操作的精准控制
java·前端·.net
良木林27 分钟前
webpack:基本打包方法
前端·webpack·node.js
青衫码上行27 分钟前
【JavaWeb学习 | 第17篇】JSP内置对象
java·开发语言·前端·学习·jsp
国服第二切图仔32 分钟前
Electron for 鸿蒙PC项目实战之tooltip-component组件
javascript·electron·鸿蒙pc