Promise状态一旦变为fulfilled或rejected便不可逆,这是其核心设计原则,旨在保障异步逻辑的确定性与可靠性,防止竞态问题和静默失败。

Promise 状态一旦从 pending 变为 fulfilled 或 rejected,就再也无法更改——这不是浏览器或引擎的限制,而是 Promise 的核心设计原则,目的是保障异步逻辑的确定性与可预测性。
状态转换只有两条单向路径
Promise 内部只允许一种初始状态(pending),且仅能通过执行器中的 resolve() 或 reject() 触发一次状态迁移:
-
pending → fulfilled:调用
resolve(value)时触发,后续所有reject()或再次resolve()都被忽略 -
pending → rejected:调用
reject(reason)或执行器中抛出未捕获错误时触发,之后任何resolve()均无效
例如:new Promise((r, j) => { r(1); j(2); r(3); }) 最终状态一定是 fulfilled,值为 1;后两次调用完全不生效。
为什么不能改?本质是为解决竞态问题
如果状态可逆,异步流程将失去基本可靠性:
立即学习“Java免费学习笔记(深入)”;
- 同一笔支付成功后,多个
.then()可能因状态被“重置”而重复提交订单 - 错误被
.catch()捕获后,又被某处误调的resolve()覆盖,导致静默失败 - 链式调用中,
fetch().then(parse).then(render)若中间 Promise 状态突变,后续环节可能拿到undefined或旧数据,引发渲染异常或权限漏洞
如何验证状态已锁定?看行为特征
原生 Promise 不暴露 .status 属性,但可通过其稳定行为确认状态是否已 settled:
- 对已 resolve 的 Promise 多次调用
.then(),每次都会立即以相同value执行回调 - 对已 reject 的 Promise 多次绑定
.catch(),每次都收到同一个reason(如Error实例) - 在 DevTools 中打断点观察,状态变更后内部字段(如 V8 的
[[PromiseState]])不再变化
注意:状态不可逆 ≠ 数据不可变
Promise 锁定的是状态和终值/据因的引用,不是值本身的内容:
-
const p = Promise.resolve({ x: 0 }); p.then(obj => { obj.x = 1; });—— 状态仍是fulfilled,但对象属性已被修改 - 业务中若依赖该对象内部字段做判断(如
if (res.data) {...}),需意识到这属于“伪状态漂移”,与 Promise 机制无关,需靠代码规范或深拷贝规避


















