Promises and async/await in JavaScript

Naman Saxena
5 min readSep 19, 2021
Photo by AltumCode on Unsplash

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 :

  1. “Before” is printed from 1st console.log() statement.
  2. displayFirstPlanet() function is called with an argument of string “Mercury” and a callback function displaySecondPlanet(). 3 seconds timer has started by setTimeout().
  3. “After” is printed from console.log() statement.
  4. 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”.
  5. And then “Earth” is printed by displayThirdPlanet().

While this looks fine, there are 2 issues with it:

  1. Generally codebases are not like this due to poor design or inability to predict and declare all functions beforehand in ever changing codebase.
  2. 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 -

Callback Hell

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 -

  1. Promises
  2. 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 :

Promise resolve is executed and promise is fulfilled

Let’s break down key points of above code to understand them.

  1. “Before” is printed from 1st console.log() statement.
  2. 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.
  3. 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.
  4. getPlanet() function is called with “Earth” parameter and the timer of 3 seconds starts due to setTimeout().
  5. “After” is printed from console.log() statement.
  6. 3 seconds timer is completed and resolve method is called because if condition is satisfied (planet==“Earth”).
  7. Now whenever resolve() function is executed, .then() method is called and takes promise returned by resolve() function.
  8. “Habitable Planet” is printed by console.log(result).
Promise reject is executed and promise is rejected
  1. 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 :

  1. pending : It is an initial state, when promise is neither fulfilled nor rejected
  2. fulfilled : When resolve() method is executed, indicating that the operation completed successfully
  3. 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 :

  1. They can only return 1 object at a time
  2. 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.
  3. 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 :

async/await Example

To implement them, we have to :

  1. Use “await” keyword before all our functions that returns Promises and we want to wait for their promise.
  2. 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.
  3. Use try-catch blocks for Error Handling
  4. 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!

--

--

Naman Saxena

23 | Software Engineer | Tech Enthusiast | Astrophile