I’m working with promises in JavaScript. I need to call a promise that returns a number 3 times. These conditions must be met:
- The promises must be run in parallel, not one after the other.
- If all the promises resolve in less than 50ms, then return the sum of all 3.
- If any of the promises take over 50ms, then return the sum of the first 2, regardless of how long they take.
I’ve made a start but I don’t know how to return early if the promises take too long:
function getPromise(): Promise<number> {
return new Promise(resolve => {
setTimeout(()=>{
resolve(Math.round(Math.random() * 10))
}, Math.random() * 100);
})
};
const TIMEOUT_MS = 50;
async function foo(){
const promises = [getPromise(), getPromise(), getPromise()];
const timeBefore = new Date().getTime()
const results: number[] = await Promise.all(promises);
const timeAfter = new Date().getTime();
const duration = timeAfter - timeBefore;
// if the duration is within 50ms then return the sum of all 3
if(duration <= TIMEOUT_MS) {
const sum: number = results.reduce((acc, current ) => acc + current, 0);
return sum
}
// todo
}
2
Answers
You’re looking for Promise.race().
Your approach of checking the timestamps could introduce a small delay because of how the event loop runs (the system is busy, the promise starts before timeBefore is recorded, …). They’re disconnected from the actual promise invocation.
Whereas the approach above is directly linked to the Promise itself, not when the main thread resumes execution.
If with the "the sum of the first 2" you mean the values of the first two promises that resolve, then you can do the following:
Create a fourth promise that expires after 50ms and resolves to the value 0, and then wait for three of those four promises to resolve: sum up the values they resolve to for getting the final result. If the 50ms timeout is one of those first three to resolve, then you’ll have effectively summed up two of the values of the three given promises (plus 0). If the 50ms-promise is not one of those first three to resolve, then you have all three values of the three given promises. In both cases you get what is asked for:
Note that the above snippet also outputs for each promise — as soon as it gets fulfilled — an array with two elements:
This allows to verify that the sum is output after three out of four promises have resolved.