DEV Community

Mrityunjaya Prajapati
Mrityunjaya Prajapati

Posted on

5 Reasons Why JavaScript Async/Await Over Promises

NodeJS supports async/await out of the box since version 7.6. I believe this is one of greatest addition to JS since 2017. If you haven’t tried it yet, here are 5 main reasons reasons with examples why you should adopt it immediately and never look back.

What is Async/Await

Async/await is a new way to write asynchronous code. Previous alternatives for asynchronous code are callbacks and promises. Async/await is actually just syntax built on top of promises. It cannot be used with plain callbacks or node callbacks.

Syntax for Async/Await and Promises

const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })

makeRequest()
Enter fullscreen mode Exit fullscreen mode

And this is how it looks with async/await:

const makeRequest = async () => {
  console.log(await getJSON())
  return "done"
}

makeRequest()
Enter fullscreen mode Exit fullscreen mode

Why Is It better?

1. Clean Code
If you compare above code then async/await code is much cleaner compare to promises

2. Error Handling
Async/await makes it finally possible to handle both synchronous and asynchronous errors with the same construct, good old try/catch

const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // this parse may fail
        const data = JSON.parse(result)
        console.log(data)
      })
  } catch (err) {
    console.log(err)
  }
Enter fullscreen mode Exit fullscreen mode

Now look at the same code with async/await.

const makeRequest = async () => {
  try {
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Return Conditional Data

const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}
Enter fullscreen mode Exit fullscreen mode

Above example is so messy and nested syntax are really tough to understand.

Look at the same code with async/await.

const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Intermediate values

You might have a situation where you call a promise1 and then use what it returns to call promise2, then use the results of both promises to call a promise3. Your code most likely looked like this

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      // do something
      return promise2(value1)
        .then(value2 => {
          // do something          
          return promise3(value1, value2)
        })
    })
}
Enter fullscreen mode Exit fullscreen mode

This same logic becomes very simple with async/await.

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}
Enter fullscreen mode Exit fullscreen mode

5. Debugging
A killer advantage when using async/await is that it’s much easier to debug. Debugging promises has always been such a pain because of 2 main reasons:

1). You can’t set breakpoints in arrow functions that return expressions.
2). If you set a breakpoint inside a .then block and use debug shortcuts like step-over, debugger will not move to the the following .then because it only steps through synchronous code

const makeRequest = () => {
   return callAPromise()
     .then(() => callAPromise())
     .then(() => callAPromise())
}
Enter fullscreen mode Exit fullscreen mode

With async/await you don’t need arrow functions as much, so you can step through await calls exactly like normal synchronous calls.

const makeRequest = async() => {
   await callAPromise()
   await callAPromise()
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)