I need to get the result of a Javascript Promise that returns the fastest, but I want to continue invoking the logic encapsulated within the other 2 "losing" promises, irrespective of who wins. Example below.
// The 3 promises I care about
const fetchFromGoogle: Promise<T> = googlePromise()
const fetchFromAmazon: Promise<T> = amazonPromise()
const fetchFromCloudflare: Promise<T> = cloudflarePromise()
// The promise that invoked its logic the fastest
const winner: T = Promise.race([fetchFromGoogle, fetchFromAmazon, fetchFromCloudflare])
In this scenario, if fetchFromAmazon
call wins in terms of speed, then I would return the result to the client, but continue running the other two promises async.
This is being executed from within a Cloudflare Worker
and the ability to return the winning promise whilst continuing the evaluation of the other functions will be supported via the waitUntil
API linked below.
I've evaluated two options:
- Some Javascript API that I'm unaware of that can do this for me
- Use something like this to determine which promises lost and run them using
Cloudflare Workers
context.waitUntil call which will ensure that the logic will continue evaluating despite having returned the result back to the client.
It's in my understanding Promise.All
would not satisfy this criteria because I would never early return the winning promise as we wait for all 3 to complete.
CodePudding user response:
You can just combine a .then()
handler with Promise.race()
. The .then()
handler lets you handle each result individually. The Promise.race()
tells you when the first one is done (and optionally what its value was):
// The 3 promises I care about
const fetchFromGoogle: Promise<T> = googlePromise().then(result => {
/* process this one here whenever it completes */
return someValue;
});
const fetchFromAmazon: Promise<T> = amazonPromise().then(result => {
/* process this one here whenever it completes */
return someValue;
});
const fetchFromCloudflare: Promise<T> = cloudflarePromise().then(result => {
/* process this one here whenever it completes */
return someValue;
});
// Tells you when the first one is done and what its value was
const winner: T = await Promise.race([fetchFromGoogle, fetchFromAmazon, fetchFromCloudflare]);
Keep in mind that Promise.race()
tracks the first promise to settle (success or failure) - it does not give you the first promise to fulfill. So, if the first promise to settle rejects, then that's what Promise.race()
will give you (the rejected promise).
You can use Promise.any()
instead to get the first fulfilled promise.