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.
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.
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);
}
})();
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.
Top comments (2)
You forgot
initiatePayment()
in the async notation.Oh my bad, that's a typo. Thanks for bringing up.