跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
JavaScriptNode.js大前端

JavaScript Promise 对象核心原理与用法

JavaScript Promise 是处理异步操作的对象,代表异步操作的最终完成或失败及其结果值。其状态包括 pending、fulfilled 和 rejected,状态不可逆且只认第一次 resolve。Promise 提供 then、catch、finally、all、race、any 等方法处理异步流程。then 返回新 Promise 实现链式调用,基于微任务机制执行。Promise 无法取消,适合一次性结果和 IO 抽象,复杂流程建议配合 async/await 使用。理解 Promise 状态机、微任务队列及错误传播机制对编写健壮异步代码至关重要。

FlinkHero发布于 2026/3/21更新于 2026/4/2916 浏览

一、Promise 是什么(不是'异步回调的语法糖')

Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。

一句话本质:

Promise 是一个'状态机 + 回调管理器',用来描述'一个未来才会确定结果的值'。

Promise 的三大特征(规范层面)
  • pending(进行中):初始状态
  • fulfilled(已成功):操作成功完成
  • rejected(已失败):操作失败
  1. 状态不可逆
    状态转换是单向的:
    • pending → fulfilled
    • pending → rejected
    • 一旦改变,永远不可再变

then 永远异步执行(微任务)

即使 resolve 是同步调用的

结果值只认第一次

resolve(1)
resolve(2)// 无效
reject(3)// 无效
那为什么总说'Promise resolved 了'?(关键)
Promise 真正的'官方状态'只有 3 个

Promise/A+ & ECMAScript 规范中:

pending fulfilled rejected 

✅ 没有 resolved 这个状态


resolved ≠ fulfilled

resolved 是一个'动词 / 过程',不是状态

规范里的原话是:

Resolve a promise with x

意思是:

尝试用某个值 x 去'解析(resolve)'Promise

用一句话精确区分(面试级)

resolved 表示 Promise 已经'被处理过',
但它最终可能是 fulfilled,也可能是 rejected

换句话说:

resolved ↓ fulfilled 或 rejected 

⚠️ 注意:
一旦进入 resolved 流程,就不再是 pending

日常口语表达(工程师黑话)
'这个 Promise resolve 了' 

通常真正意思是:

  • then 被触发了
  • 异步成功了
  • 不是 pending 了

👉 不是规范用语

一个非常容易被问懵的面试题
Q:Promise.resolve(Promise.reject(1)) 的状态是什么?
Promise.resolve(Promise.reject(1)).then(()=> console.log('fulfilled'),err=> console.log('rejected', err))
正确理解:
  • 外层 Promise 被 resolve 了
  • 但 resolve 的值是一个 rejected Promise
  • 所以最终状态是:
rejected(1) 

⚠️ 这就是 'resolved ≠ fulfilled' 的最好例子

创建 Promise
const promise = new Promise((resolve, reject)=>{
  // 异步操作
  setTimeout(()=>{
    const success = true;
    if(success){
      resolve('操作成功');
    }else{
      reject(new Error('操作失败'));
    }
  },1000);
});

二、Promise 的状态模型(核心)

 ┌─────────────┐
 │ pending     │
 └──────┬──────┘
        │
 ┌──────┴──────┐
 │             │
┌───────────┐ ┌───────────┐
│ fulfilled │ │ rejected  │
└───────────┘ └───────────┘
内部必然有的字段(实现角度)
{
  status:'pending'|'fulfilled'|'rejected',
  value: any,
  reason: any,
  onFulfilledCallbacks:[],
  onRejectedCallbacks:[]
}

这不是猜的,是 Promise/A+ 实现的必然结构


三、Promise 的常见方法

then() - 处理成功和失败

then 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 fulfilled 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。then 方法返回的是一个新的 Promise 对象实例;因此可以用链式写法,即 then 的后面再调用另一个 then 方法。

promise.then((result)=>{
  console.log('成功:', result);
},(error)=>{
  console.log('失败:', error);
});
catch() - 捕获错误

相当于第二个回调函数指向 reject;catch 方法还有一个作用,就是在执行 resolve 回调时,如果出现错误抛出异常,不会停止运行,而是进入 catch 方法中。

promise .then(result=> console.log(result)).catch(error=> console.error('错误:', error));
finally() - 无论成功失败都执行

finally 方法用于指定不管 Promise 对象最后状态如何,都会执行 finally。finally 方法的回调函数不接收任何参数。这表明 finally 方法里面的操作应与状态无关,不依赖于 Promise 的执行结果。

promise .then(result=> console.log(result)).catch(error=> console.error(error)).finally(()=> console.log('操作结束'));
all() - 所有都成功

方法接收一个平行任务。它接收一个数组;数组的每一项都是一个 Promise 对象;当数组的每一项的状态都是 fulfilled 的时候,all 方法的状态会变成 fulfilled。如果有一项状态变成 rejected,那么 all 方法的状态就会变成 rejected

  • 全部 fulfilled → fulfilled(数组)
  • 任意 rejected → 立即 rejected(短路)
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(values=> console.log(values));// [1, 2, 3]
.catch(error=> console.error(error));
race() - 最先完成的

和 all 方法一样,接收的参数是一个每项都是 Promise 的数组。但是与 all 不同的是,当最先执行的事件完成之后,就直接返回 Promise 对象的值,如果第一个 Promise 对象状态是 fulfilled,那自身状态就是 fulfilled。

  • 谁先 settle,用谁
const p1 = new Promise(resolve=>setTimeout(resolve,500,'快'));
const p2 = new Promise(resolve=>setTimeout(resolve,1000,'慢'));
Promise.race([p1, p2]).then(value=> console.log(value));// "快"
any() - 任意一个成功

只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。
Promise.any() 跟 Promise.race() 方法很像,只有一点不同,就是 Promise.any() 不会因为某个 Promise 变成 rejected 状态而结束,必须等到所有参数 Promise 变成 rejected 状态才会结束。

  • 任意 fulfilled → fulfilled
  • 全 rejected → rejected(AggregateError)
Promise.any([p1, p2]).then(value=> console.log(value));

四、then 的真正含义(99% 的人理解错)

then ≠ 注册回调这么简单
p.then(onFulfilled, onRejected)

then 做了 3 件极其重要的事:

  1. 返回一个新的 Promise(链式调用的根源)
  2. 把回调包装成'微任务'
  3. 处理返回值,决定新 Promise 的状态

then 的返回规则(重点)
then 回调返回值新 Promise 状态
普通值fulfilled,值为返回值
Promise等这个 Promise
thenable 对象按 Promise 解析
throw errorrejected
不写回调值穿透 / 错误冒泡
Promise.resolve(1).then(v=> v +1).then(v=> Promise.resolve(v +1)).then(v=>{
  throw 'err'
}).catch(e=> console.log(e))

五、Promise 链为什么不会'嵌套地狱'?

核心原因:then 返回新 Promise
const p2 = p1.then(...)

本质结构:

p1 ──then──▶ p2 ──then──▶ p3 

而不是:

p1 └── then └── then └── then 
Promise Resolution Procedure(规范核心)

伪代码:

if(x === promise) throw TypeError 
if(x is Promise) adopt its state 
if(x is object/function&& has then) call then 
else resolve(x)

这套规则就是防止循环引用、防止多次 resolve、防止同步 thenable 乱入


六、Promise 的微任务本质(Event Loop 级别)

经典面试题
console.log(1)
Promise.resolve().then(()=>{
  console.log(2)
})
setTimeout(()=>{
  console.log(3)
})
console.log(4)

输出顺序:

1 4 2 3 
原因
  • Promise.then → Microtask
  • setTimeout → Macrotask

async / await 本质
async function foo(){
  await bar()
  console.log(1)
}

等价于:

function foo(){
  return Promise.resolve(bar()).then(()=>{
    console.log(1)
  })
}

👉 await = Promise.then 的语法糖


七、Promise 的'错误传播机制'

错误冒泡规则
  1. throw 等价于 reject
  2. 下游 then 没有 onRejected → 继续向下冒泡
  3. .catch() 本质是 .then(null, onRejected)
Promise.resolve().then(()=>{
  throw new Error('boom')
}).then(()=>{
  console.log('never')
}).catch(err=>{
  console.log(err.message)
})

一个隐蔽坑(非常高级)
Promise.resolve().then(()=>{
  setTimeout(()=>{
    throw new Error('boom')
  })
}).catch(()=>{
  console.log('catch?')
})

👉 catch 不会捕获

原因:

Promise 只能捕获 then 链中的同步异常 & 返回的 Promise 异常


八、Promise 的核心(面试杀器)

不要求背,但必须理解

最小核心能力:

then(onFulfilled, onRejected){
  return new Promise((resolve, reject)=>{
    // 状态判断
    // 回调队列
    // 微任务包装
    // 返回值处理(Promise Resolution)
  })
}

面试官真正想问的是:

  • 你理解'状态不可逆'吗?
  • 你知道 then 为什么返回新 Promise 吗?
  • 你明白微任务队列吗?
  • 你理解 Promise Resolution Procedure 吗?

九、什么时候不该用 Promise(架构视角)

Promise 的局限性
  • 无法取消 Promise,中途无法取消
  • 错误处理需要谨慎;如果不设置回调函数,Promise 的内部抛出的错误不会反映到外部
  • 需要配合 async/await 使用更佳
  • 当处于 pending 状态时,无法得知目前进行到哪个阶段了

❌ 滥用 Promise:

  • 复杂流程控制(应使用 async/await + try/catch)
  • 大量并发控制(应配合并发池)
  • 事件型逻辑(Promise 不可多次 resolve)

✅ Promise 最适合:

  • 一次性结果
  • IO 抽象
  • 组合式异步

十、总结

Promise 是现代 JavaScript 异步编程的核心,理解它的工作原理和最佳实践对于编写健壮的异步代码至关重要。

Promise 解决的不是'异步',而是
'用可组合、可推理的方式描述未来值的状态变化'

目录

  1. 一、Promise 是什么(不是“异步回调的语法糖”)
  2. Promise 的三大特征(规范层面)
  3. 那为什么总说“Promise resolved 了”?(关键)
  4. Promise 真正的“官方状态”只有 3 个
  5. resolved ≠ fulfilled
  6. 日常口语表达(工程师黑话)
  7. 一个非常容易被问懵的面试题
  8. Q:Promise.resolve(Promise.reject(1)) 的状态是什么?
  9. 正确理解:
  10. 创建 Promise
  11. 二、Promise 的状态模型(核心)
  12. 内部必然有的字段(实现角度)
  13. 三、Promise 的常见方法
  14. then() - 处理成功和失败
  15. catch() - 捕获错误
  16. finally() - 无论成功失败都执行
  17. all() - 所有都成功
  18. race() - 最先完成的
  19. any() - 任意一个成功
  20. 四、then 的真正含义(99% 的人理解错)
  21. then ≠ 注册回调这么简单
  22. then 的返回规则(重点)
  23. 五、Promise 链为什么不会“嵌套地狱”?
  24. 核心原因:then 返回新 Promise
  25. Promise Resolution Procedure(规范核心)
  26. 六、Promise 的微任务本质(Event Loop 级别)
  27. 经典面试题
  28. 原因
  29. async / await 本质
  30. 七、Promise 的“错误传播机制”
  31. 错误冒泡规则
  32. 一个隐蔽坑(非常高级)
  33. 八、Promise 的核心(面试杀器)
  34. 九、什么时候不该用 Promise(架构视角)
  35. Promise 的局限性
  36. 十、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • DIAMOND 基因序列快速比对工具使用及超算集群并行计算指南
  • 当 AI 接管研发流程,传统工程师的天花板在哪?未来 2 年软件工程发展预判
  • Camunda 服务任务(Service Task)的 5 种实现方式详解
  • Python 爬虫自动化选股:潜力股筛选实战
  • Claude Code 完全精通指南:实现产品与研发协同提效
  • Spring AI 实战:基于 Ollama 构建离线私有化 AI 服务
  • Llama3 中文模型微调与部署实战指南
  • Ubuntu 22.04 安装与配置 Openclaw 指南
  • OpenClaw 安装与飞书机器人接入指南
  • PowerShell 无法激活 Python 虚拟环境的解决方案
  • Flutter 三方库 xpath_selector 的鸿蒙适配与 HTML 解析实战
  • Coze 长期计划构建 AI 工具榜单整理 Agent 与钉钉自动推送指南
  • 鸿蒙金融理财全栈项目:生态合作、用户运营与数据变现优化
  • 使用 TRAE CN 与 MCP 协议将 MasterGo 设计稿转为前端代码
  • 汽车雷达多径环境下幽灵目标检测算法研究
  • FPGA 实现 HDMI 输出完全攻略:从接口原理到 4K 显示全流程
  • 纯 Java 版个人所得税计算模拟器源码实现
  • VSCode Copilot 认证失败排查与修复技巧
  • Java List 按对象属性值连续分割为多个子 List
  • Coze 专属 AI 应用开发:从智能体构建到 Web 部署指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online