Promise.all 和 Promise.race 有效地使所有承诺“得到处理”,这是一种记录在案的行为吗?

Posted

技术标签:

【中文标题】Promise.all 和 Promise.race 有效地使所有承诺“得到处理”,这是一种记录在案的行为吗?【英文标题】:Is it a documented behavior that Promise.all and Promise.race effectively make all promises "handled"? 【发布时间】:2021-01-26 18:27:17 【问题描述】:

在下面,代码unhandledRejection 不会因为p2 而被解雇,即使它也被拒绝,尽管晚于p1

process.on('unhandledRejection', (reason, promise) => 
  console.log(`unhandledRejection: $reason`));

async function delay(ms) 
  await new Promise(r => setTimeout(r, ms));


const p1 = async function f1()
  await delay(100);
  throw new Error("f1");
();

const p2 = async function f2()
  await delay(200);
  throw new Error("f2");
();

try 
  await Promise.race([p1, p2]);
  //await Promise.race([p1]);

catch (e) 
  console.error(e.message);

如果我像这样更改注释行:

  //await Promise.race([p1, p2]);
  await Promise.race([p1]);

...然后unhandledRejection 确实会因为p2 而被解雇,正如预期的那样。 Promise.all() 观察到相同的行为。

因此,Promise.racePromise.all 有效地阻止了 unhandledRejection 事件,因为承诺没有赢得比赛但仍然被拒绝。这是记录在案的行为吗?我似乎在规范中找不到任何提及。

【问题讨论】:

【参考方案1】:

是的,Promise.racePromise.all“处理”您传递给它们的所有承诺的结果,无论该结果是否与来自race/all 的承诺的结算有关。因此,Promise.race 中的“失败”承诺仍然得到处理,尽管来自 Promise.race 的承诺只反映了获胜承诺所发生的事情。同样,如果 Promise.all 因为其输入承诺之一拒绝而拒绝,则稍后来自其他输入承诺的任何拒绝都会被处理,但不会对其进行任何处理。

您可以在规范中看到这一点,它将处理程序与传入的每个承诺的履行和拒绝都挂钩,例如在PerformPromiseRace 的步骤 3.i 中:

执行? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).

【讨论】:

不错!所以我可以在我的代码中依赖这种行为,我有一个用例:) 感谢您提供信息丰富的答案! 后续,so as it turns, unhandledRejection 如果在拒绝时没有附加任何处理程序,则将被触发。如果我们稍后附加处理程序并不重要。有趣的是,这就是它与 .NET Task 的不同之处,后者可以保持“休眠”状态,并且只有在垃圾收集时仍然未被观察到时才会触发 UnobservedTaskException

以上是关于Promise.all 和 Promise.race 有效地使所有承诺“得到处理”,这是一种记录在案的行为吗?的主要内容,如果未能解决你的问题,请参考以下文章

手写Promise.all和Promise.race

实现promise.all方法

JavaScript的Promise.all和Promise.race

(转载)理解和使用Promise.all和Promise.race

如何使用并区分Promise.all和Promise.race?

vue promise.all使用