-
-
Save unscriptable/06f8984d6cb0fd6be1c0 to your computer and use it in GitHub Desktop.
// This is the function we will use to call Promise.race(). | |
// logWinner is simply a function that races two promises | |
// and logs the "winner" of the race as a side effect. | |
function logWinner (p1, p2) { | |
Promise.race([p1, p2]).then(console.log.bind(console)); | |
} | |
// Here are 2 promises, p1 and p2. p2 always resolves | |
// first, since p1 resolves in 20 ms, and p2 resolves | |
// in 10 ms. By any reasonable definition of "race", | |
// p2 should be the winner. | |
var p1 = new Promise(function(resolve) { | |
setTimeout(function() { resolve('p1'); }, 20); | |
}); | |
var p2 = new Promise(function(resolve) { | |
setTimeout(function() { resolve('p2'); }, 10); | |
}); | |
// Given the same inputs, you would expect that Promise.race | |
// would behave the same *no matter when you call it*. However, | |
// Promise.race behaves differently depending on *when* it is | |
// called. In an async environment (e.g. browsers, node), | |
// you can never determine when something will be called in | |
// all but the most trivial cases. | |
// If Promise.race is called *before* any of the raced promises | |
// are resolved, logWinner logs the correct winner, "p2". | |
setTimeout(function() { logWinner(p1, p2); }, 0); | |
// If Promise.race is called *after* any of the raced promises | |
// are resolved, logWinner logs the lowest resolved promise | |
// in the array, "p1". | |
setTimeout(function() { logWinner(p1, p2); }, 50); | |
// Therefore, Promise.race is non-deterministic. |
Please see these:
You case looks like a new variation of the first I've not seen before though it's not entirely unexpected.
By the time you call Promise.race, both promises are resolved. At this point Promise.race doesn't have the information to order them.
The work around that would be to check if resolved immediately after hooking it to the event in the correct order up front though I don't know of an explicit mechanism for that (it's an encapsulate state).
Basically do Promise.race() for each added timer? It's annoying as it needs to be order aware that things should finish in that way but not really much you can do about it. Technically speaking if the issue I found is fixed then it could be possible to put an autoincrement order id on the promises. Promise.race only works properly when all or all but one promises are in a pending state.
It's turning up to the finishing line and seeing both are there already. It doesn't have an action replay.
Thanks for the assist, I missed that in my POC.
I do not see the point for two main reasons:
then should be clear that since at the first call p2 is the winner, but on the second call also p1 is solved and since in the race is checked before p2, p1 wins on the second run,... and everything makes sense.
As a small counter-proof is enough to set higher timeouts in the promises definition (enough higher than the timeouts for the logWinner calls):
I hope this could clarify
Have fun