为什么在 setTimeout 内部和外部会产生不同的 Promise 状态结果(使用 Promise.race)?

问题描述 投票:0回答:1

promise (p1, p2, p3) 在

getStates()
外部和
setTimeout
内部的
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
函数来自MDN并使用Promise.race

function promiseState(promise) { const pendingState = { status: "pending" }; return Promise.race([promise, pendingState]).then( (value) => value === pendingState ? value : { status: "fulfilled", value }, (reason) => ({ status: "rejected", reason }), ); }
这都是来自 

MDN Promise.race

 页面
的示例。

我认为所有 Promise 都应该返回pendingState 对象,但在

setTimeout

 函数中情况并非如此。

javascript promise
1个回答
3
投票
promise(p1, p2, p3) 的执行方式有何不同

这是很多人对承诺的一个重要误解。承诺没有被“执行”。 Promise 只是报告正在完成的事情,它并不“做”这件事。这是

观察异步操作结果的标准方法。 在该代码中,异步操作是计时器。当您创建承诺(前三行代码)时,计时器就会启动。在 new Promise

返回承诺之前,您传递的函数

new Promise 会被同步调用。该函数的工作是启动 Promise 将报告的异步工作。因此,这三个承诺所报告的工作都开始一次,就在开始时,而不是稍后当您通过getStates

观察它们时。
启动这些计时器后,您将检查承诺状态两次:
立即:这是在任何计时器有机会触发之前,因此所有承诺都显示为待处理。

100ms 后:此时,您的两个 Promise 已得到解决(

p1
    在 100ms 后履行,
  • p3
  • 在 100ms 后被拒绝),其中一个仍处于待处理状态(因为
  • p2
     尚未解决) 200 毫秒)。因此,您看到的结果是 
    p1
     已履行,
    p2
     待决,
    p3
     被拒绝。
    关键是承诺计时器在您创建承诺时启动,而不是稍后。
    
    
  • 总而言之,检测 Promise 的状态是一个“坏主意”。这就是为什么 Promise 没有内置的方法来做到这一点。相反,编写代码使其对承诺的履行和/或拒绝做出反应,而无需在设置这些反应时担心承诺的状态。像
promiseState

这样的函数是一种反模式,在尝试理解 Promise 如何工作的过程中用途非常有限。即便如此,它也可能会产生误导——当您看到这些信息时,这些信息可能已经过时了。


© www.soinside.com 2019 - 2024. All rights reserved.