JavaScript 里的 Promise 到底应该如何理解?

最简单、最不容易误解的理解方式是下面这三句话:

  1. Promise 是一个**“未来会给出结果的承诺”**
  2. 这个承诺只有三种最终状态:等待中 → 成功(fulfilled) 或 失败(rejected),而且一旦成功或失败就不可逆
  3. Promise 的真正价值在于:它把“异步操作”从回调地狱里解放出来,变成了可链式、可组合、可并行、可错误统一的“值”

用生活中的比喻来理解(最推荐的入门视角)

把 Promise 想象成**“外卖订单”**:

现实中的外卖订单 对应到 Promise 关键点说明
你下单了 new Promise(...) 创建了一个 promise 订单已经存在,但饭还没到
商家正在做饭 / 骑手在路上 promise 处于 pending(等待中) 目前还拿不到结果
骑手把饭送到你门口 resolve(饭) → fulfilled 成功了,拿到了你想要的东西
商家说没菜了 / 骑手摔了送不了 reject(原因) → rejected 失败了,告诉你为什么
送到或取消后,订单状态不再变 状态一旦变为 fulfilled 或 rejected 就不可逆 非常重要!不会反复送也不会反复取消
你可以告诉朋友“饭到了叫我” .then() 注册成功回调 “到了就给我打电话”
你也可以说“送不了也告诉我” .catch() 或 .then(…, onRejected) “送不了也要通知我”
不管成功失败都要给小费 .finally() “不管怎样都要付配送费”

Promise 最核心的四件事(必须记住)

  1. Promise 本身是同步创建的,但它的状态变化是异步的

    console.log(1);
    const p = new Promise((resolve) => {
      console.log(2);
      setTimeout(() => {
        resolve(3);
        console.log(4);
      }, 0);
    });
    p.then(() => console.log(5));
    console.log(6);
    
    // 输出顺序:1 → 2 → 6 → 5 → 4
    
  2. .then() 永远返回一个新的 Promise(链式调用的根本原因)

    fetch(url)
      .then(res => res.json())          // 返回一个新的 promise
      .then(data => console.log(data))  // 又返回一个新的 promise
      .catch(err => console.error(err));
    
  3. 错误会穿透所有 .then() 直到被 .catch() 捕获(类似 try-catch 的错误冒泡)

    Promise.resolve(1)
      .then(() => { throw new Error("炸了") })
      .then(() => console.log("不会执行"))
      .catch(err => console.log(err.message)); // → 炸了
    
  4. Promise.all / allSettled / any / race 是并行处理的利器

    方法 特点 只要其中一个… 结果状态取决于… 典型使用场景
    Promise.all 最常用 失败 → 整体失败 全部成功才成功 所有图片/接口都必须加载成功
    allSettled 无论成功失败都等全部完成 不会短路 永远 fulfilled 批量操作,想知道每个结果
    any 第一个成功的就算成功(ES2021) 第一个 fulfilled 就成功 全部失败才失败 并发请求,只要有一个成功即可
    race 谁先完成(成功或失败)谁赢 第一个 settled 就结束 跟随最快那个的状态 超时控制、竞速、取最快响应

2025–2026 年最推荐的现代写法(async/await + try-catch)

// 推荐写法(清晰、可读性高、容易调试)
async function fetchUserData(userId) {
  try {
    const res = await fetch(`/api/users/${userId}`);
    
    if (!res.ok) {
      throw new Error(`HTTP ${res.status}`);
    }
    
    const data = await res.json();
    const profile = await fetchProfile(data.profileId);
    
    return { user: data, profile };
  } 
  catch (err) {
    console.error("获取用户数据失败:", err);
    throw err; // 可以继续向上抛,也可以在这里处理降级逻辑
  }
  finally {
    // 无论成功失败都会执行(关闭 loading、释放资源等)
    hideLoading();
  }
}

总结:一句话记住 Promise 的本质

Promise 不是用来“做异步”的,而是用来“管理异步结果”的。

它把原本杂乱无章的回调,变成了:

  • 可链式调用
  • 可并行处理
  • 可统一错误处理
  • 可等待多个任务
  • 状态明确、不可逆的“异步值”

一旦你把 Promise 理解成“带有状态的未来值”,而不是“一种特殊的回调”,你就真正懂了。

有具体哪一段代码或哪种业务场景的 Promise 写法让你困惑吗?可以贴出来,我帮你改成最清晰的写法。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐