Promises and async/await in JavaScript
In this we are going to discuss about Promises, async/await and why we need them in JavaScript. If you are not familiar with JavaScript Callback, you can read my previous story for some context:
Introduction
In previous article we discussed need of Callback in JavaScript and briefly discussed Callback Hell.
Let’s take a look at few very simple examples to understand Callback Hell and then we will be able to understand need of Promises.
Example:
In this example we are just consoling first 3 planets using Callback and setTimeout() . Of course you can console them directly, we are just using this to understand Callback Hell concept without complex examples.
So the order of execution will be :
- “Before” is printed from 1st console.log() statement.
- displayFirstPlanet() function is called with an argument of string “Mercury” and a callback function displaySecondPlanet(). 3 seconds timer has started by setTimeout().
- “After” is printed from console.log() statement.
- Once 3 seconds are completed, “Mercury” is printed and displaySecondPlanet() function callback is called with arguments. And similarly after 3 seconds timer “Venus” is printed and displayThirdPlanet() function callback is called with argument “Earth”.
- And then “Earth” is printed by displayThirdPlanet().
While this looks fine, there are 2 issues with it:
- Generally codebases are not like this due to poor design or inability to predict and declare all functions beforehand in ever changing codebase.
- Even if we do manage to write code this way and we don’t remember logic of a function, each time we have to go back to retrace the logic flow, which can be time consuming.
Hence, the same code is written somewhat like this -
As you can notice, even with our simple console.log() example the same code has started to become less readable and hard to maintain.
And the solutions of this issue is -
- Promises
- async/await
Promise
A promise in JavaScript is an object of class Promise that may return a single value asynchronously. Promises are used as an alternative of Callback to flatten the code structure and have more control on when we want to handle the results. They also provide more user friendly way of handling errors and unlike Callback where parameters are input to the function and also Callback function that we want to be called, promise provides a cleaner way to write code.
Let’s take a look at an example to understand and discuss promises before jumping into too much theory :
Let’s break down key points of above code to understand them.
- “Before” is printed from 1st console.log() statement.
- The asynchronous function (also known as executor) is passed as an argument to Promise class constructor which then creates a promise object. getPlanet() function returns this object whenever it is executed.
- It is necessary for executor function to have resolve and reject in-built methods passed as parameters, we will discuss their importance in a bit.
- getPlanet() function is called with “Earth” parameter and the timer of 3 seconds starts due to setTimeout().
- “After” is printed from console.log() statement.
- 3 seconds timer is completed and resolve method is called because if condition is satisfied (planet==“Earth”).
- Now whenever resolve() function is executed, .then() method is called and takes promise returned by resolve() function.
- “Habitable Planet” is printed by console.log(result).
- Similarly whenever reject() function is executed, .catch() method is called and it handles error.
States of Promise
Since promise is a proxy of value and not the value itself, it has 3 states :
- pending : It is an initial state, when promise is neither fulfilled nor rejected
- fulfilled : When resolve() method is executed, indicating that the operation completed successfully
- rejected : When reject() method is executed, indicating that the operation failed
Now let’s implement Promises in our initial example and see how it solves our problems.
Notice, after removing Callbacks it becomes more readable and easier to keep track of code control flow of our asynchronous code.
Cons of Promises
But there are few disadvantages of Promises that we should be aware of :
- They can only return 1 object at a time
- They are to be polyfilled as they are not compatible with old browsers. Polyfill means we have to provide additional code for older browsers that do not support this feature.
- Callbacks are much faster and memory efficient than Promises
async/await
Another alternative is async/await of JavaScript. They are syntactic sugar for Promises.
Let’s implement them in our example to discuss them :
To implement them, we have to :
- Use “await” keyword before all our functions that returns Promises and we want to wait for their promise.
- Use “async” keyword before our function that is calling all asynchronous functions and it tells a function to return a promise or else JavaScript will implicitly wrap value in resolved promise.
- Use try-catch blocks for Error Handling
- Call our async function allThreePlanets()
Conclusion
Callbacks are still useful for different scenarios as they are faster and more memory efficient and are also used with many in-built functions like addEventListener() during DOM Manipulation. But it is great to have Promises and async/await in your JavaScript arsenal. You can do further reading about them in MDN docs or anywhere on the internet as internet is filled with tons of informative articles about them.
Hi smart folks of the internet! This was my 2nd medium story, do let me know if you found any of it informative or if you have any suggestions/criticism.
Thanks!