Tomáš Hübelbauer Tomáš Hübelbauer - 3 months ago 10
Javascript Question

How to handle promises as they resolve?

Currently, this code print out a zero, because the first promise in the array resolves immediately.



const promises = [];
const promiser = (number) => new Promise((resolve, reject) => window.setTimeout(() => resolve(number), number * 100));
for (let index = 0; index < 10; index++) {
const promise = promiser(index);
promises.push(promise);
}

Promise.race(promises).then(r => console.debug(r));





I'm looking to make it so that once the quickest promise resolves, it is removed from the
promises
array and a new
Promise.race
call is made with the remaining promises, repeating until no promise is left.

Since
Promise.race
returns the result of the promise, not the resolved promise itself, though, I am unable to identify which promise was it that resolved and I do not know which one to remove from the array. Is there a way to know this? I suppose I could return a complex object with some sort of a correlation key and the result, but that seems weird. I was hoping second parameter of the
Promise.race
callback would be index of the promise, but that's not the case and it doesn't make sense either since the
then
is just a
then
of another promise, so how would it know that it should return some index anyway. Can you think of a better way?

Also, I run all the promises with the first
race
, but that shouldn't be a problem for subsequent
race
s, right? In case another promise resolved in the meantime before the subsequent
race
call was made, it should just return it, no problem, correct? And if multiple promises did resolve in the meantime, it would just return the first (in array order or in resolution order?) and then the next
race
would return the second and so on… Right?

BTW I also though I could walk the array and remove promises that have
isResolved
, but that's not a real thing. Even if it was, though, this would completely break for the case where multiple promises resolve between the calls to
race
.

Answer

You can return an identifier to the promises

const promises = [];
const promiser = (number, id) => new Promise((resolve, reject) => window.setTimeout(() => resolve({ number, id }), number * 100));
for (let index = 0; index < 10; index++) {
  const promise = promiser(index, "id_" + index);
  promises.push(promise);
}

Promise.race(promises).then(r => console.debug(r.id));

Anyway if you are working with a promise library such as bluebird you can find some utility that can help you structure your code better ( like Promise.reduce or Promise.any )