Promise

义项:JavaScript异步编程对象
Promise

Promise是JavaScript语言中用于表示异步操作最终结果的对象,它把「尚未完成、将来会有结果」这一状态封装为可传递的值。它只有进行中、已成功、已失败三种状态,状态一旦确定便不再改变,从而让异步流程可以用链式调用和统一的错误处理来表达[1]。自2015年随ECMAScript 2015成为语言标准后,Promise成为浏览器与Node.js中异步编程的基础设施,并被后续的async函数沿用[2]。

目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

Promise是JavaScript中的一种对象,代表一次异步操作在将来产生的结果或失败原因。按Promises/A+规范的定义,与Promise交互的主要入口是它的then方法,调用方通过该方法登记回调,以便在操作成功时取回值、在失败时取回失败原因。这种对象把「结果还没到」这件事本身变成可以传递、可以等待的普通值,因此异步任务的调度逻辑不必写在回调内部。

状态是Promise定义中的核心。一个Promise只能处于pending(进行中)、fulfilled(已成功)与rejected(已失败)三种状态之一;处于pending时可以转向另外两种之一,一旦进入fulfilled或rejected,就不能再转向任何其他状态,并分别固定持有一个值或一个失败原因。状态确定且值固定的Promise在社区文档中常被合称为settled,中文常译作已定型[3]。

原理

Promise通过构造函数创建,构造时传入一个执行器函数,执行器同步获得resolve与reject两个函数作为参数,自行在异步操作结束时调用其中之一[4]。执行器返回的值会被忽略;如果在执行器中抛出错误,且尚未调用resolve或reject,该Promise转为已失败状态[4]。若执行器既不调用这两个函数、又不安排任何异步任务,Promise就会永久停留在进行中状态[4]。

then方法接受onFulfilled与onRejected两个可选参数,两者都必须等到当前执行栈只含平台代码之后才可被调用,且成功或失败回调各自最多执行一次。同一个Promise上多次调用then时,回调按登记顺序依次执行;then本身返回一个新的Promise,若回调返回了值x,则按解析过程处理,若x本身是一个thenable或Promise,新Promise会跟随x的最终状态。这一「返回新Promise」的规则是链式写法成立的前提。

回调进入微任务队列而非立即执行,是Promise时序的关键。即使Promise已经确定,then登记的函数也不会同步运行,而是排入微任务,在当前任务结束、执行栈清空后运行。因此同步代码先输出、then回调后输出的顺序可以稳定复现。错误在链中具有传递性质:某一环被拒绝且没有处理函数时,拒绝原因会继续向后传给下一个处理函数。

除实例方法外,Promise构造函数还提供组合多个任务的静态方法。Promise.all在所有输入的Promise都成功时以结果数组兑现,任一失败即立刻以该原因拒绝;Promise.allSettled则等待全部操作结束再汇总为数组。Promise.race以最先确定的那一个Promise的状态为准,Promise.any则以最先成功的一个为准。

发展历程

Promise并非JavaScript独创的机制。按社区梳理,这一概念可追溯到1976年的相关研究,其思想与future、延迟计算等构造同源,此后在多种语言的并发库中以std::promise、Future等形式出现[3]。在JavaScript生态中,较早被广泛使用的类似实现是jQuery的Deferred对象,但它与后来的规范并不完全一致[3]。

为了在不同实现之间达成互操作,2012年形成了Promises/A+这一开放规范,它只规定then方法的行为,并附带测试用例,从而使各家Promise库可以互相替换使用。在该标准进入语言规范之前,社区已出现Q、bluebird、when等遵循该规范的库[5]。

ECMAScript 2015(即ES6)把Promise纳入语言标准,浏览器与Node.js随后原生提供该对象,Mozilla基金会的开发者文档将浏览器全面支持的时间点记为2015年7月[4][2]。在此基础上,ES2017引入的async函数与await运算符以Promise为底层机制,异步代码可以写成接近同步的分支与循环结构[3]。

应用

最常见的用途是发起网络请求并处理其响应。现代浏览器提供的Fetch API返回Promise,网络成功与否用状态表示,响应内容再通过then或await取出[3]。在没有原生Promise接口的旧式回调API上,通常用构造函数把回调包装成Promise,从而统一调用方式;例如把setTimeout包装为返回Promise的等待函数。

串行流程可以用then链表达:前一环返回新的Promise,后一环即在其完成后执行,从而避免层层缩进的回调嵌套,并在链尾用catch集中处理前面各环节的错误。并行且互不依赖的任务则交给Promise.all,待全部结果就绪后一并处理,常见的做法是同时请求多份数据再统一渲染[3]。

Promise也作为基础设施支撑了多项平台能力与框架设计。JavaScript指南列举的组合工具都已建立在Promise之上,服务端的数据库驱动与Web框架同样以Promise作为异步接口的默认形态[3]。在资源预加载、超时控制等场景中,Promise.race可以把请求与计时器放在一起竞速,由先结束的一方决定后续流程[6]。

局限

Promise本身没有取消协议。规范与标准文档都没有提供取消已建立Promise的接口,一旦创建即开始执行,无法从外部中途终止,只能通过resolve或reject改变状态[1]。实践中通常借助AbortController去取消底层的异步操作,而非取消Promise对象本身。

在进行中状态下,外部无法得知任务进展到哪一步,只能等待最终结果,因此不适合用来表达持续产生多个值的流式场景[1]。此外,若某个Promise被拒绝而始终没有附加处理函数,该失败不会自动向调用方传播,需要运行环境额外上报:浏览器会在全局作用域派发unhandledrejection事件,Node.js则触发同名的进程事件[7][8]。

组合方法也有边界。Promise.all在遇到第一个失败时即整体拒绝,其余操作虽仍在执行,但其结果不会再通过该Promise返回,这可能造成不易察觉的状态残留;需要全部结束的场合应改用Promise.allSettled。另外,把互不依赖的任务用then串行排布会让它们相互阻塞,在不需要顺序的地方应保持并行。

参见

  • 回调函数 —— 早期实现异步流程的主要方式,Promise试图缓解其层层嵌套的问题。

  • async函数 —— 以Promise为底层机制、允许用await暂停等待的语法特性。

  • Fetch API —— 返回Promise的现代网络请求接口。

  • 事件循环 —— 决定Promise回调何时以微任务形式执行的运行机制。

  • Node.js —— 原生提供Promise并以进程事件上报未处理拒绝的服务端运行环境。

参考资料

  1. Promise 对象 [引用日期2026-10-29]
  2. educative.io 上的网页 [引用日期2026-10-29]
  3. Promise的前世今生 [引用日期2026-10-29]
  4. Promise() 构造函数 [引用日期2026-10-29]
  5. 请选择投诉理由 [引用日期2026-10-29]
  6. Javascript 中的神器——Promise [引用日期2026-10-29]
  7. Window: unhandledrejection 事件 [引用日期2026-10-29]
  8. 事件:'unhandledRejection'#>>>>>>>>>>> [引用日期2026-10-29]
词条评价
词条统计

浏览次数:0 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-28T18:50:53Z

历史版本

本条目引用的词条
Promises/A+ Fetch API 回调函数 async函数 事件循环 Node.js