You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何setTimeout内外通过Promise.race获取的Promise状态结果不同?

问题:为何不同时机调用getStates(),Promise状态检测结果有差异?

在MDN提供的Promise.race相关示例代码中,为何在setTimeout外部调用getStates()函数,与在setTimeout内部调用该函数时,p1、p2、p3这三个Promise的执行状态检测结果存在差异?原本以为所有Promise都会返回pendingState对象,但在setTimeout内的情况并非如此。

示例代码

const p1 = new Promise((res) => setTimeout(() => res(100), 100));
const p2 = new Promise((res) => setTimeout(() => res(200), 200));
const p3 = new Promise((res, rej) => setTimeout(() => rej(300), 100));

async function getStates() {
  console.log(await promiseState(p1));
  console.log(await promiseState(p2));
  console.log(await promiseState(p3));
}

console.log("Immediately after initiation:");
getStates();
setTimeout(() => {
  console.log("After waiting for 100ms:");
  getStates();
}, 100);

promiseState函数实现

function promiseState(promise) {
  const pendingState = { status: "pending" };

  return Promise.race([promise, pendingState]).then(
    (value) =>
      value === pendingState ? value : { status: "fulfilled", value },
    (reason) => ({ status: "rejected", reason }),
  );
}
回答:

核心原因:Promise状态变化时机 + 事件循环机制

差异的本质是两个规则的叠加:

  1. Promise.race的执行逻辑:Promise.race([A, B])会返回第一个进入"已敲定"状态的结果。如果参数里有非Promise值(比如这里的pendingState普通对象),会被直接包装成已resolve的Promise,值就是该对象。
  2. JavaScript事件循环的执行顺序:
    • 初始化后立即调用getStates():此时p1、p2、p3内部的setTimeout回调都还没执行(setTimeout回调属于宏任务,要等当前同步代码跑完才会处理),三个Promise全处于pending状态。所以Promise.race([pending的Promise, pendingState])会优先返回已resolve的pendingState,检测结果全是pending。
    • 等待100ms后调用getStates():此时p1和p3的100ms setTimeout回调已经执行,p1被resolve为100,p3被reject为300,两者都完成了状态转换;但p2的200ms回调还没触发,依旧是pending。所以:
      • 检测p1时,Promise.race([已resolve的p1, pendingState])会返回p1的resolve值,最终输出{ status: "fulfilled", value: 100 }
      • 检测p3时,Promise.race([已reject的p3, pendingState])会触发reject分支,输出{ status: "rejected", reason: 300 }
      • 检测p2时,还是返回pendingState,输出{ status: "pending" }

补充说明

Promise的状态一旦从pending变为fulfilled或reject就会永久固定,所以100ms后检测p1、p3时,它们已经完成状态转换,Promise.race自然会优先选择已敲定的Promise,而非作为普通值的pendingState。

内容的提问来源于stack exchange,提问作者Nic B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:10:10