How to use Async/Await in JavaScript

Asynchronous code is always hard to wrap our minds around. The new addition to ES8 which has been around for a while now are the async/await functions. Before the introduction of async/await we used callbacks and promises.

If you are a new to JavaScript, you can learn what promises are, and jump right into async/await. If you are still using promises, it is time for you to learn async/await.

Downside of older methods

To understand, why async/await functions are preferred compared to Promises, we need to understand what are some problems with using Promises.

Callback Hell

Imagine your code has a whole lot of callbacks nested with a series of function calls. It is not uncommon to see code with plenty of nested callbacks, which is called the callback hell. Your becomes difficult to read, maintain and test at this point. In my opinion, code that is not easy to read, is not good code. This is something async/await can help with.

Error Handling

Both callbacks and Promises do not offer a clean way to handle errors. You would have a hard time finding out which Promise, threw the error if you are within a bunch of nested promises. Async/await shines in error handling as well.

Why async/await functions were introduced?

To mitigate some of the pain points that come with writing asynchronous code using Promises or callbacks, async/await has been introduced. They allow you to write asynchronous code in a synchronous manner. It allows you to write asynchronous code that will avoid any callback-hell and also makes sure the code is clean and maintainable. Hence, the introduction of async/await which is easier to read and maintain.


The functions with “async” keyword indicates that the function always returns a Promise. If the function throws an error, then the Promise will be rejected. If the function returns a value, then the Promise will be resolved. Simple enough!

async function add(a,b) {
return a+b;


The await keyword works only inside async functions. await makes JavaScript wait until the promise is resolved.

Keep in mind that you cannot use await in regular functions. It works only within async functions.

Let’s take a look at some code snippets. We can use multiple await statements.

async function ToDoOne() { ... }
async function ToDoTwo(value) { ... }
async function ToDoThree(value) { ... }
async function ToDos() {
  let resultOne = await ToDoOne();
  let resultTwo = await ToDoTwo(resultOne);
  let finalResult = await ToDoThree(resultTwo);
  return finalResult;
// Call ToDos()

We can use multiple await statements. ToDoThree() will await the completion of ToDoTwo(). And ToDoTwo() will await the completion of ToDoOne(). 

If you observe the code snippet above, it looks very close to synchronous code. That is the main benefit of using async/await functions. They make asynchronous code look like synchronous code, hence making it easy to read and maintain. The await keywords ensures that JavaScript waits until each async function returns its result.

async/await with Promise.all

If you need to wait for multiple promises, you can wrap them in a Promise.all and await. Instead of using multiple await statements like the previous example, if you want your promises to run at the same time, you can use Promise.all() within your async function.

// wait for the array of results
let results = await Promise.all([

Error Handling using try & catch

In async/await  errors can be handled in a much simpler manner, using try/catch blocks just like any other synchronous code. any code that we want to run after the promise is settled, we can use finally.

let isOurPromiseFinished = false;
const myAsyncAwaitBlock = async (str) => {
  try {
    // Promise is resolved
    const myPromise = await returnsAPromise(str);
    console.log(`using async/await, ${res}`);
  } catch(error) {
    // Promise is rejected
  } finally {
    isOurPromiseFinished = true;


Benefits of Async/Await

  1. Clean Code –  Of all the approaches that are available to us today, async/await results in the cleanest and most maintainable code.
  2. Better Error Handling – Errors can be handled in a much simpler manner, using try/catch blocks just like any other synchronous code.
  3. Simple Debugging – Setting breakpoints through await calls is possible and easier to debug through, compared to Promises and callbacks.

Recap Async/Await

  • async functions return a promise.
  • The await keyword before a promise, makes JavaScript wait until that promise settles.
  • await cannot be used outside an async function.
  • There can be multiple await statements within a single async function.
  • async/await makes your asynchronous code written in synchronous fashion, hence making it readable.
  • The code is readable, maintainable and suitable for error handling.


Async/await is one of the best features that has been added to JavaScript. If you have tons of code with Promises, I encourage you to refactor your codebase to use async/await instead. You will be surprised to see how much more readable and clean your code will be after the rewrite.

If you are looking for a great JavaScript course, checkout Mosh’s course on JavaScript and become an expert.

Adhithi Ravichandran is a Senior Software Engineer based in Kansas City. She is currently working on building mobile apps using React Native for critical healthcare scenarios. Adhithi is a regular conference speaker at various tech conferences. Adhithi graduated with a Masters degree in Computer Science from the University of Kansas and has been in the tech industry for over 7 years. She has worked on several technologies over the years, and one of her recent favorite is React Native.
Tags: ,

Leave a Reply

Connect with Me
  • Categories
  • Popular Posts