DEV Community

Cover image for Practical Async JavaScript

Practical Async JavaScript

Bogdan Varlamov on May 23, 2024

Introduction Let's take a moment to brush up on some JavaScript async concepts together. What is Asynchronous? First off, le...
Collapse
 
oculus42 profile image
Samuel Rouse

Nice article! I always enjoy seeing articles about promises and async JavaScript!

On the "retries" logic, though, you've created a single, global attempt counter. I would suggest a slight change to passing the values into the function. This keeps it isolated in scope and also uses good patterns when dealing with recursion. Something like this, perhaps:

async function makeApiCallWithRetries(value, maxRetries = 5, attempt = 1) {
  try {
    const result = await fakeApiCall(value);
    return result;
  } catch (error) {
    if (attempt >= maxRetries) {
      throw new Error(`Max retries reached: ${error}`);
    }
    console.log(`Attempt ${attempt} failed: ${error} - for value: ${value}`);
    return makeApiCallWithRetries(value, maxRetries, attempt + 1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Using default values allows them to be auto-populated on the first call and then incremented only within the recursive call, and it allows us to specify different maxRetries for different APIs, in case some are very flaky.

Collapse
 
bgdnvarlamov profile image
Bogdan Varlamov

Yes, that's a great suggestion. In production code, I would definitely implement it as you demonstrated, with a default value
Thanks!

Collapse
 
gauravchandra profile image
Gaurav Chandra

this is a great article. however, there is an opinion in the dev community that we should not be using async/await as it blocks the thread. Instead we should use observables. Care to shed a light on this?

Collapse
 
oculus42 profile image
Samuel Rouse

Async/await is non-blocking. They are literally a different way of writing promises, and if it help you can think of Promises as roughly equivalent to observables that are guaranteed to will only ever produce one event. They cover different use cases, but they are async.

Observables may be used to initiate promises, e.g. the classic RxJS Wikipedia search demo from MIX11, but the promise is still non-blocking

I would appreciate it if you have any links to information on this topic, in case I am misunderstanding or missing context.

Collapse
 
deepakbaid profile image
deepakbaid97

Using await is what blocks the thread. I think that's what he meant

Thread Thread
 
brandon_4ac813c611a5340fe profile image
Brandon

Seconding what @oculus42 said: unless there's a misunderstanding or missing context, this is still untrue.

Await is not blocking. It defers execution of subsequent code until after the awaited code completes, but it doesn't block the thread.

Collapse
 
schemetastic profile image
Schemetastic (Rodrigo)

Very useful!

Collapse
 
lisacee profile image
Lisa Cee

I love the idea of using Math.random to simulate success and error states. I often have to prototype UI before an API is ready and this works better than having to write two functions and comment out the state I don't want.

Collapse
 
lotfijb profile image
Lotfi Jebali

Insightful

Collapse
 
respect17 profile image
Kudzai Murimi

Insightful

Collapse
 
shinny22 profile image
Shinny22

Thanks that help me to understand async use in React.

Collapse
 
jangelodev profile image
João Angelo

Hi Bogdan Varlamov,
Thanks for sharing

Collapse
 
developedbyjk profile image
developedbyjk

A Perfect Place to Revise Quick!

Collapse
 
madhan_rock_9ffa73f834eb6 profile image
Madhan Rock

Clean and concise ✌️

Collapse
 
joo_carlosrovedaostrov profile image
João Carlos Roveda Ostrovski • Edited

Wouldn't be a better practice to use Promise.all or Promise.allSettled?

Refering to the last example in the article.

Collapse
 
vutunglaminfo profile image
Vu Tung Lam • Edited

Promise.all and Promise.allSettled both accept an array of Promise objects and return a single Promise object upon success. So what does the returned Promise resolve to, eventually?

If you use Promise.all then the returned Promise would resolve to an array of values which the input promises resolve to, respectively. And it would reject if ANY of the input promises rejects.

On the other hand, if you use Promise.allSettled then the returned Promise would ALWAYS resolve to an array of objects indicating whether each individual input promise resolves or not ; and if it resolves, what the resolved value is.

So you use Promise.all when you want all the input promises to succeed (resolve). And you would use Promise.allSettled when you want to inspect which input promises succeeded and which failed.

To further consolidate your understanding: Promise.allSettled returns a Promise that will always succeed/resolve. Why? You may want to reread what the returned Promise resolves to when you use Promise.allSettled, as mentioned above.

Collapse
 
joo_carlosrovedaostrov profile image
João Carlos Roveda Ostrovski

Thank you!