简体   繁体   English

Promise.any() 和 Promise.race() 有什么区别

[英]What is the difference between Promise.any() and Promise.race()

What is the difference between Promise.any() and Promise.race() , and how do they get used differently? Promise.any()Promise.race()有什么区别,它们的使用方式有何不同?


From MDN ,来自MDN

Also, unlike Promise.race(), which returns the first settled value, this method returns the first resolved value.此外,与返回第一个确定值的 Promise.race() 不同,此方法返回第一个确定值。 This method will ignore all rejected promises up until the first promise that resolves.此方法将忽略所有被拒绝的承诺,直到第一个 promise 解决。

So that brings me to, the difference between resolved and settled .这让我想到了解决解决之间的区别。 Which then brought me to the MDN promises page , which then brought me to States and Fates然后将我带到 MDN 承诺页面然后将我带到States and Fates

Being settled is not a state, just a linguistic convenience.落户不是state,只是语言方便。

So we have Promise.any and Promise.race for linguistic convenience?所以我们有Promise.anyPromise.race为了语言方便? ie there is no difference.没有区别。 Another instance of this equality, is "A promise whose fate is unresolved is necessarily pending."这种平等的另一个例子是“命运未决的 promise 必然悬而未决。” and "We say that a promise is settled if it is not pending, ie if it is either fulfilled or rejected.".和“我们说,如果 promise 不是未决的,即如果它被履行或被拒绝,它就会被结算。”。

So if a promise is resolved, it is not unresolved, so it is not pending.因此,如果一个 promise 已解决,则它不是未解决的,因此它不是待处理的。 So then, if it's not pending, it's settled.那么,如果它不是未决的,它就已经解决了。 So resolved === settled.于是解决了===解决了。

Promise.race and Promise.any do different things: Promise.racePromise.any做不同的事情:

Promise.race is settled as soon as any of the promises you feed it settle, whether they are fulfilled or rejected. Promise.race在您提供的任何承诺结算后立即结算,无论它们是否被履行或拒绝。

Promise.any is settled as soon as any of the promises you feed it is fulfilled or they are all rejected, in which case it's rejected with an AggregateError . Promise.any一旦你提供的任何承诺被履行全部被拒绝,它就会被结算,在这种情况下,它会被AggregateError拒绝。

The chief differences are:主要区别在于:

  1. race 's promise is rejected when the first promise you give it is rejected;当你给它的第一个 promise 被拒绝时, race的 promise 被拒绝; any doesn't, because another promise may be fulfilled instead. any没有,因为另一个 promise 可能会被实现。

  2. any 's promise's rejection reason will be an AggregateError , but race 's rejection reason will be the rejection reason from the promise that was rejected. any的 promise 的拒绝原因将是AggregateError ,但race的拒绝原因将是来自被拒绝的 promise 的拒绝原因。

So if you pass them both an array of two promises, and one of the promises is rejected, then afterward the other promise is fulfilled, the promise from Promise.race will be rejected (because the first promise to settle was rejected) and the promise from Promise.any will be fulfilled (because although the first promise was rejected, the second was fulfilled). So if you pass them both an array of two promises, and one of the promises is rejected, then afterward the other promise is fulfilled, the promise from Promise.race will be rejected (because the first promise to settle was rejected) and the promise from Promise.any将被满足(因为虽然第一个 promise 被拒绝,但第二个被满足)。 Eg:例如:

 const a = new Promise((_, reject) => setTimeout(reject, 100, new Error("a"))); const b = new Promise((resolve) => setTimeout(resolve, 200, "b")); Promise.race([a, b]).then( value => { console.log(`race: fulfilled with ${value}`); }, reason => { console.log(`race: rejected with ${reason.message}`); } ); Promise.any([a, b]).then( value => { console.log(`any: fulfilled with ${value}`); }, reason => { console.log(`any: rejected with ${reason.errors.map(({message}) => message).join()}`); } );

With a JavaScript engine that has Promise.any (or a polyfill), that outputs使用具有Promise.any (或 polyfill)的 JavaScript 引擎,输出

race: rejected with a
any:  fulfilled with b

Play with various outcomes here (there's a very rough incomplete stand-in for Promise.any included if your browser doesn't have it yet):在这里玩各种结果(如果您的浏览器还没有,则包含Promise.any非常粗略的不完整替代):

 addFakeAnyIfMissing(); document.querySelector("input[value='Start Again']").addEventListener("click", run); run(); function setupPromise(name) { return new Promise((resolve, reject) => { const div = document.querySelector(`[data-for="${name}"]`); const btnFulfill = div.querySelector("input[value=Fulfill]"); const btnReject = div.querySelector("input[value=Reject]");; const display = div.querySelector(".display"); btnFulfill.disabled = btnReject.disabled = false; display.textContent = "pending"; btnFulfill.onclick = () => { resolve(name); display.textContent = `fulfilled with ${name}`; btnFulfill.disabled = btnReject.disabled = true; }; btnReject.onclick = () => { reject(new Error(name)); display.textContent = `rejected with Error(${name})`; btnFulfill.disabled = btnReject.disabled = true; }; }); } function run() { const a = setupPromise("a"); const b = setupPromise("b"); const raceDisplay = document.querySelector("[data-for=race].display"); const anyDisplay = document.querySelector("[data-for=any].display"); raceDisplay.textContent = anyDisplay.textContent = "pending"; Promise.race([a, b]).then( value => { raceDisplay.textContent = `fulfilled with ${value}`; }, reason => { raceDisplay.textContent = `rejected with ${reason.message}`; } ); Promise.any([a, b]).then( value => { anyDisplay.textContent = `fulfilled with ${value}`; }, reason => { anyDisplay.textContent = `rejected with ${reason.errors.map(({message}) => message).join()}`; } ); } function addFakeAnyIfMissing() { if (.Promise,any) { // VERY ROUGH STANDIN. not a valid polyfill class AggregateError extends Error {} Object,defineProperty(Promise, "any", { value(iterable) { return new Promise((resolve; reject) => { const errors = []; let waitingFor = 0; for (const value of iterable) { const index = waitingFor++. Promise.resolve(value);then( value => { resolve(value); --waitingFor, }; reason => { errors[index] = reason. if (--waitingFor === 0) { reject(Object,assign(new AggregateError(); {errors})); } } ); } }), }: writable, true: configurable; true }); } }
 <div data-for="a"> Promise A <input type="button" value="Fulfill"> <input type="button" value="Reject"> <span class="display"></span> </div> <div data-for="b"> Promise B <input type="button" value="Fulfill"> <input type="button" value="Reject"> <span class="display"></span> </div> <div data-for="race"> <code>Promise.race([a, b])</code>: <span class="display"></span> </div> <div data-for="any"> <code>Promise.any([a, b])</code>: <span class="display"></span> </div> <input type="button" value="Start Again">

This chart from the proposal may help:提案中的这张图表可能会有所帮助:

There are four main combinators in the Promise landscape . Promise 格局中有四个主要组合子

 +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−−−−−-+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− -----------------------+------------------+ | name |姓名 | description |说明 | | | +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−−−−−-+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− -----------------------+------------------+ | Promise.allSettled | Promise.all 已解决 | does not short-circuit |不短路 | Added in ES2020 |在 ES2020 中添加 | | | Promise.all | Promise.all | short-circuits when an input value is rejected |输入值被拒绝时短路 | Added in ES2015 |在 ES2015 中添加 | | | Promise.race | Promise.race | short-circuits when an input value is settled |输入值确定时短路 | Added in ES2015 |在 ES2015 中添加 | | | Promise.any | Promise.any | short-circuits when an input value is fulfilled |满足输入值时短路 | this proposal |这个提议| +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−-+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− ----------------------+------------------+

Continuing with your question...继续你的问题...

Another instance of this equality, is "A promise whose fate is unresolved is necessarily pending."这种平等的另一个例子是“命运未决的 promise 必然悬而未决。” and "We say that a promise is settled if it is not pending, ie if it is either fulfilled or rejected.".和“我们说,如果 promise 不是未决的,即如果它被履行或被拒绝,它就会被结算。”。

So if a promise is resolved, it is not unresolved, so it is not pending.因此,如果一个 promise 已解决,则它不是未解决的,因此它不是待处理的。 So then, if its not pending, its settled.那么,如果它没有挂起,它就解决了。 So resolved === settled.于是解决了===解决了。

I can see how you got there, but you can't invert it like that.我可以看到你是如何到达那里的,但你不能像那样反转它。 :-) A resolved promise can be pending. :-) 一个已解决的 promise 可能处于未决状态。 It's just that an unresolved promise is definitely pending.只是一个未解决的 promise肯定悬而未决。

The states are:这些州是:

  • pending待办的
  • fulfilled完成
  • rejected被拒绝

You can resolve a promise ( A ) to another promise ( B ), which means that while A may still be pending, nothing can change what's going to happen to it;您可以将 promise ( A ) 解析为另一个 promise ( B ),这意味着虽然A可能仍处于未决状态,但没有什么可以改变它将发生的事情; its fate is sealed, it will be fulfilled or rejected according to what happens to B .它的命运是注定的,它会根据B发生的事情来实现或拒绝。

Here's an example of a pending resolved promise:这是一个待解决的 promise 示例:

 const b = new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() < 0.5) { resolve("all good"); } else { reject(new Error("ugh")); } }, 100); }); // (Being verbose for clarity) const a = new Promise((resolve, reject) => { resolve(b); // Now, `a` is pending, but resolved // No matter what else we do, `a`'s fate is tied to // `b`'s. For instance, this does nothing: resolve("foo"); // Neither does this: reject(new Error("foo")); }); b.then(value => { console.log(`b was fulfilled: ${value}`); }).catch(reason => { console.log(`b was rejected: ${reason.message}`); }); a.then(value => { console.log(`a was fulfilled: ${value}`); }).catch(reason => { console.log(`a was rejected: ${reason.message}`); });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM