DEV Community

loading...
Cover image for Breaking down Async/Await 🔥

Breaking down Async/Await 🔥

Aswathprabhu R
Crazy on Web!
・3 min read

Async/Await is one of the amazing inclusions in javascript. It provides a first-class way of writing asynchronous code in a synchronous style. Yes, you heard it right, this pattern allows a developer to write code to be human-readable, not only for machines. Code is not only for machines to execute but also for humans to interpret and develop.

Before digging the syntactic sugar, let's get our hands into some predecessors in asynchronous programming to know why this pattern can truly be a silver bullet in the asynchronous world.

Callbacks

Callbacks were the solution for async programming before promises landed. It was one of the pain parts of javascript at that time considering the code flow and complexity. Yes, it troubled the developer a lot. Inversion of control was one of the main concerns to avoid this pattern of programming.

For example, consider this code chunk

somethirdPartyLibrary.checkout(function doPayment() {
 initiatePayment();
})

Consider, you run an online boot camp where you use a third-party service to handle the checkout process for you. Once the library decides that its time to charge the customers, it invokes the callback(doPayment) to record the payment. Everything is fine if the library invokes the callback once. What if due to some issues on their end, the library invokes the callback multiple times, or doesn't invoke it at all. This causes some of the serious issues and may break the trust of customers.

OMG

This is the Inversion of control we discussed above. We are handing control of charging our customers to the library. This is one of the weird patterns to be avoided and it is still in use.

And here comes the feature request from nowhere that our customers should be notified regarding the status of their subscription. Using callbacks we will implement the feature this way.

somethirdPartyLibrary.checkout(function doPayment() {
 initiatePayment(function notifyAboutSuccess() {
     showSuccess();
   }, function notifyAboutFailure() {
     showFailure();
   }
 );
})

This results in multiple nesting of callbacks and is somewhat confusing 😓 , right? Now, if we want to perform an action that should succeed success notification we will nest it as a callback to notifyAboutFailure() and very soon we are into callback hell. Our code flow would be like this then.

Confused

The Saviour Promises

Promises paved the way for more human-readable code. Using promises, our scenario can be implemented as,

somethirdPartyLibrary.checkout()
.then(initiatePayment)
.then(showSuccess)
.catch(showFailure)

Here the flow is neat and also the control of charging our customers is with us. Some may have doubts that what if somethirdPartyLibrary.checkout is resolved multiple times will then execute multiple times? No that's not the case, a promise can be resolved or rejected only once. Promises are so far so good, the only concern here is that if some task depends upon a promise to resolve then we would normally wrap all of them in the then event handler right? What can be a magical solution that allows us to write asynchronous code in a synchronous fashion?

Here comes the silver bullet 🎯

Using Async/Await our implementation can be rewritten,

(async function() {
  try {
    await somethirdPartyLibrary.checkout()
    await initiatePayment();
    showSuccess();
  } catch(err) {
    showFailure(err);
  }
})();

Deal breaker
This is truly a magic right?

Breaking'em down

This kind of flow is achieved with Generators in javascript. Yes, Async/Await is implemented with the help of generators and promises underhood.

function resumeHandleCheckout() {
    iterator.next();
}

function* handleCheckout() {
    yield someThirdPartyLibrary.checkout();
    yield initiatePayment();
    showSuccess();
}

let iterator = handleCheckout();

let promiseFromLibrary = iterator.next();


promiseFromLibrary
.then(resumeHandleCheckout)
.then(resumeHandleCheckout)
.catch(showFailure);

Can you get the underhood mechanism of Async/Await? It handles all the complexity and provides us a syntactic sugar.

This is truly a deal-breaker as it allows the developer to write async code in synchronous style and now more human-readable one. Feel free to share this post with your colleagues as well.

Discussion (3)

Collapse
thorstenhirsch profile image
Thorsten Hirsch

You forgot initiatePayment() in the async notation.

Collapse
theaswathprabhu profile image
Aswathprabhu R Author • Edited

Oh my bad, that's a typo. Thanks for bringing up.