The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.
Taken from MDN site.
I have 5 promises and I need to know once any 2 promises are resolved, taking performance under consideration.
const sleep = ms =>
new Promise(r => setTimeout(r, ms))
async function swimmer (name) {
const start = Date.now()
console.log(`${name} started the race`)
await sleep(Math.random() * 5000)
console.log(`${name} finished the race`)
return { name, delta: Date.now() - start }
}
const swimmers =
[ swimmer("Alice"), swimmer("Bob"), swimmer("Claire"), swimmer("David"), swimmer("Ed") ];
Promise.race(swimmers)
.then(({ name }) => console.log(`*** ${name} is the winner!!! ***`))
.catch(console.error)
This will return the fastest swimmer but I would like to print once I get 2 promises resolved.
How can I do it?
CodePudding user response:
You could write a custom implementation of Promise.race
that returns a promise that is resolved with the result of 2 promises that are resolved before others.
Following code example shows an implementation:
function customPromiseRace(promiseArr, resolvePromiseCount) {
return new Promise((resolve, reject) => {
// array to store the result of resolved promises
const resolvedPromises = [];
// used to prevent adding the result of promises in the
// "resolvedPromises" that we don't need
let alreadyResolved = false;
promiseArr.forEach(p => {
p.then(result => {
// push the promise fulfilment value in the "resolvedPromises"
// array only if we haven't already resolved the promise returned by the
// "customPromiseRace" function
if (!alreadyResolved) {
resolvedPromises.push(result);
if (resolvedPromises.length === resolvePromiseCount) {
alreadyResolved = true;
resolve(resolvedPromises);
}
}
}).catch(reject);
});
});
}
Demo
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function swimmer(name) {
const start = Date.now();
console.log(`${name} started the race`);
await sleep(Math.random() * 5000);
console.log(`${name} finished the race`);
return { name, delta: Date.now() - start };
}
const swimmers = [
swimmer('Alice'),
swimmer('Bob'),
swimmer('Claire'),
swimmer('David'),
swimmer('Ed'),
];
function customPromiseRace(promiseArr, resolvePromiseCount) {
return new Promise((resolve, reject) => {
const resolvedPromises = [];
let alreadyResolved = false;
promiseArr.forEach(p => {
p.then(result => {
if (!alreadyResolved) {
resolvedPromises.push(result);
if (resolvedPromises.length === resolvePromiseCount) {
alreadyResolved = true;
resolve(resolvedPromises);
}
}
})
.catch(reject);
});
});
}
customPromiseRace(swimmers, 2).then(console.log).catch(console.error);