Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Chidozie C. Okafor
Chidozie C. Okafor

Posted on • Originally published atdoziestar.Medium on

     

JavaScript Under the Hood: `Promise.race`

Imagine entering your preferred eatery, where two cooks are in a competition to serve you the fastest. Although they are both talented and skillful cooks, their cooking speeds can differ according on the item they are preparing.

There’s a special rule in this restaurant: no matter how far along the other chefs are, you get to receive and eat the meal that the first chef finishes preparing. The second dish is never shown to you or given a taste; it is just put away. It’s all about who serves you first in this “race”.

The “Promise.race” Restaurant

In Javascript ther is a concept known as “Promise.race”. Imagine this as a competition between two or more promises, similar to our cooks, to see who can finish first.

Think of the pledges as chefs in our restaurant. They are both in the process of finishing a chore or cooking a food for you. The result of your dinner (or the code you receive) depends on the chef (or promise) who finishes first.

let chefA = new Promise((serve) => {    setTimeout(serve, 500, 'Burger');});let chefB = new Promise((serve) => {    setTimeout(serve, 100, 'Salad');});
Enter fullscreen modeExit fullscreen mode

chefA prepares a burger in 500 milliseconds, while chefB can whip up a salad in just 100 milliseconds.

Who Serves First?

In our special restaurant, you don’t get both dishes. You only get the dish of the chef who finishes first. This is where Promise.race comes into play

Promise.race([chefA, chefB]).then(dish => {  console.log(`You got served: ${dish}`);  // "You got served: Salad"});
Enter fullscreen modeExit fullscreen mode

Given our chefs’ preparation times, you’ll receive the salad, because chefB serves faster!

But What About the Buzzer?

We have a catch here at the restaurant. A loud siren will go off, indicating that you are free to leave without receiving a dish, if neither chef serves you within the allotted time.

In our code, this “buzzer” is a timeout. It ensures that procedures don’t take longer than necessary:

let chefSpecial = new Promise((serve) => {    setTimeout(serve, 6000, 'Special Dish');});let buzzer = new Promise((_, kickOut) => setTimeout(() => kickOut('Buzzer Alert: Too slow!'), 5000));Promise.race([chefSpecial, buzzer]).then(dish => {    console.log(`You got served: ${dish}`);}).catch(alert => {    console.error(alert);    // "Buzzer Alert: Too slow!"});
Enter fullscreen modeExit fullscreen mode

The buzzer (timeout) will sound initially, indicating that the meal preparation took longer than five seconds.

How we are using “Promise.race” at HubHub

The Promise.race Mechanism:

This is where things get interesting! Inside the loop, a race is set up between two promises using Promise.race:

  • The actual YouTube search: youtube.search(query, { type }).
  • A “buzzer” or timeout promise: This promise doesn’t resolve with any data; instead, it rejects with an error if the specified timeout (TIMEOUT) is reached without getting a response from the YouTube search.

Handling the Race Outcome:

  • Successful Search: If the YouTube search finishes first (before the timeout), the response is returned to the caller.
  • Timeout Reached: If the “buzzer” promise is the faster one (meaning the search took too long), it rejects with a “Request Timeout” error.
  • Rate-Limiting Error (Status 429): If YouTube indicates that you’re making requests too quickly (status code 429), the function will catch this error and retry the search.
async searchYoutube(query, type) {    if (!validateInputs(query, type)) {      throw new Error('Invalid inputs for search.');    }    let retries = 0;    while (retries < MAX_RETRIES) {      try {        const response = await Promise.race([          youtube.search(query, { type }),          new Promise((_, reject) => setTimeout(() => reject(new Error('Request Timeout')), TIMEOUT)),        ]);        return response;      } catch (error) {        if (error.message === 'Request Timeout' || (error.response && error.response.status === 429)) {          retries++;          console.log(`Attempt ${retries} failed. Retrying...`);        } else {          Sentry.captureException(error);          throw new HttpException(INTERNAL_SERVER_ERROR, 'Internal Server Error');        }      }    }    throw new Error('Failed to retrieve search results after maximum retries.');  }
Enter fullscreen modeExit fullscreen mode

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
websilvercraft profile image
websilvercraft
  • Work
    CEO at nowhere
  • Joined

I'm also usingPromise.race to add timeouts to fetch calls, in production to make sure the calls don't remain hanged up to consume server's resources.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software Engineer & Backend Magician 🎩 | Python, TypeScript, Node.js & Golang | Conjuring Microservices, Apache Kafka & Scalable Solutions | Empowering Organizations with a Touch of Code Sorcery 🧙‍♂️✨
  • Location
    Regensburg Germany
  • Education
    University Of Benin
  • Pronouns
    Mr
  • Work
    Backend Engineer @ ProPro Productions
  • Joined

More fromChidozie C. Okafor

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp