JavaScript异步编程:Promise与async/await

1.什么是Promise

Promise,承诺,在 JavaScript 中,它是一种异步编程的解决方案,Promise 是一个 表示异步操作最终完成或失败的对象,它提供了一种标准化的方式来处理异步结果。你可以把它想象成一个"容器",里面包裹着一个未来才会知道结果的操作(比如网络请求、定时器、文件读取等)。

Promise 的三种状态

  • Pending(进行中):初始状态,操作尚未完成。
  • Fulfilled(已成功):操作成功完成,Promise 返回结果值。
  • Rejected(已失败):操作失败,Promise 返回错误原因。

Promise 构造函数接收一个函数(称为 执行器函数,executor ),这个执行器函数会被 立即同步调用 (也就是 new Promise 时立刻执行)。

执行器函数的两个参数:

  • resolve(value)

    将 Promise 的状态从 pending 变为 fulfilled(已完成),并传递一个值给后续的 .then()。

    value参数规则:

    参数类型 行为
    普通值 直接作为成功值传递,例如 resolve(42) 或 resolve("data")。
    Promise 对象 当前 Promise 会"跟随"这个 Promise 的状态(成为它的镜像)。
    无参数 等同于 resolve(undefined)。
  • reject(value)

    调用它表示 异步操作失败 ,并将 Promise 状态从 pending 变为 rejected(失败)。

    可以传递一个错误原因(如 reject(new Error("超时"))),这个错误会被.then()的第二个参数 或.catch() 捕获(向下传递)。通常推荐传递 Error 对象(如 reject(new Error("失败"))),但可以是任意值(如字符串、数字等)。

2.Promise.then()的作用

  • 接收上游 Promise 的结果。
  • 返回新 Promise 供下游使用。
  • 隐式 处理 resolve/reject,开发者只需关心业务逻辑。
javascript 复制代码
// 伪代码:.then() 的底层实现
function then(onFulfilled) {
  return new Promise((resolve, reject) => {
    const handleResult = (value) => {
      try {
        const result = onFulfilled(value); // 执行你的回调,value指当前promise的result
        // 自动处理返回值!
        if (result instanceof Promise) {
          result.then(resolve, reject); // 跟随返回的 Promise
        } else {
          resolve(result); // 普通值直接 resolve
        }
      } catch (error) {
        reject(error); // 捕获错误并 reject
      }
    };
    this.addHandler(handleResult); // 监听当前 Promise 状态
  });
}

3.async/await语法糖

Promise 构造函数接收一个函数(称为 执行器函数,executor),执行器函数的 函数体*就是定义 "未来要发生的动作" ,通常是一个异步操作(如 setTimeout、fetch、fs.readFile 等)。

当这个 未来动作完成时 ,你需要 手动调用 resolve 或 reject 来改变 Promise 的状态。每次手动调用resolve和reject会非常繁琐,所以async/await语法糖应运而生

对比示例:用 Promise 和 async/await 实现同一逻辑

场景:先请求用户数据,再请求用户订单,最后合并结果。

手动控制 Promise 的写法(繁琐)

javascript 复制代码
function getUserData(userId) {
  return new Promise((resolve, reject) => {
    fetch(`/users/${userId}`)
      .then(response => {
        if (!response.ok) reject(new Error("用户数据请求失败"));
        return response.json();
      })
      .then(data => resolve(data)) // 手动 resolve
      .catch(error => reject(error)); // 手动 reject
  });
}

function getOrders(userId) {
  return new Promise((resolve, reject) => {
    fetch(`/orders/${userId}`)
      .then(response => {
        if (!response.ok) reject(new Error("订单请求失败"));
        return response.json();
      })
      .then(data => resolve(data)) // 手动 resolve
      .catch(error => reject(error)); // 手动 reject
  });
}

// 链式调用(仍需手动处理嵌套)
getUserData(123)
  .then(user => {
    getOrders(user.id)
      .then(orders => console.log({ user, orders }))
      .catch(error => console.error("订单错误:", error));
  })
  .catch(error => console.error("用户错误:", error));

需要反复手动调用 resolve/reject 。

多层嵌套时容易陷入"回调地狱"(虽然比传统回调好,但依然不够直观)。

用 async/await 的写法(简洁)

javascript 复制代码
async function fetchUserAndOrders(userId) {
  try {
    const user = await fetch(`/users/${userId}`).then(res => res.json()); // 自动解析 Promise
    const orders = await fetch(`/orders/${user.id}`).then(res => res.json());
    console.log({ user, orders });
  } catch (error) {
    console.error("请求失败:", error); // 统一捕获错误
  }
}

fetchUserAndOrders(123);
相关推荐
夏幻灵8 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
三天不学习8 小时前
Egg.js 4 突然爆火,原因是否归结于AI 原生落地需求爆发?
前端·javascript·全栈·egg.js
xcs194059 小时前
前端 vue 的前端页面debugger 进不去
前端·javascript·vue.js
小宋102114 小时前
A2UI从零实战:Agent安全生成交互界面与事件回传
javascript·人工智能·安全·交互
大包子15 小时前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js
lerhxx15 小时前
AI 应用中的上下文管理 —— 从"上下文窗口"到"分层压缩"的工程实践
前端·javascript
Mahut15 小时前
我在 Mac 上做了个本地剪辑器
javascript·架构·产品
汉堡大王952716 小时前
GPT-6 上线 48 小时,我扒开了 Intelligent UI 的运行机制:DIL、沙箱 Worker 和一个 React 式协调器
前端·javascript·后端
hai_android16 小时前
Chat 聊天模块功能总结
前端·javascript·vue.js
创世虚拟世界16 小时前
我做了一个 3D 虚拟世界基底,基于这个再做 3D 虚拟世界或者元宇宙,会事半功倍
javascript·人工智能·3d·gitee·虚拟现实