Asynchronous code with async/await

DamCosset
11.3K views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Introduction

I wrote about promises and generators being introduced in ES6. Another way to make asynchronous code look synchronous almost made it in ES6, but not quite: async/await. This functionality is built on top of promises. Let's take a look at it.

Syntax

The syntax is as follow: you must declare a function to be async:

const asyncFunction = async () => {
  // This is a good start
}

// or

const asyncFunction = async function(){
  // Old school function keyword? I like it!
}

Then, inside this async function, you can use the await keyword to tell the function it should wait for something:

const asyncFunction = async () => {
  const step1 = await fetchingData() // Wait for this

  const step2 = await savingData() // Then wait for that

  // Do something else
}

You can still keep your promises

I mentioned that async/await is build on top of promises. An async function returns a promise. This means you can call .then() and .catch() on them:

Ok, what is happening here?

  • We create an async function called writeAndRead.
  • The function has two await keywords: first, we wait for the function to write to the file test.txt
  • Second, we wait for the function to read the test.txt file we just wrote to.
  • We store that in a variable and return it
  • Because async functions return promises, I can use .then() after calling the writeAndRead() function.

Pretty sweet huh? We don't even need to specify a resolve() and reject() method anymore. Which brings me to the next point.

You are all the same errors to me <3

Let's assume a scenario where you have promises-based logic and non-promises-based logic ( synchronous and asynchronous ) in your code. You would probably handle errors this way:

const someComplicatedOperation = () => {
  try {
    // Blablabla do something
    db.getUsers()     //promise
    .then( users => {
      const data = JSON.parse( users )    // ===> What if this fail bro?
      console.log(data)
    })
    .catch( err => {
      console.log('You broke your promise!!!')
    })
  }
  catch( err ){
    console.log('I caught a error. But I only catch synchronous stuff here :(')
  }
}

That's right. The try/catch won't catch the JSON.parse error because it is happening inside a promise. A rejected promise triggers the .catch() method, but NOT the other catch. That's annoying, we have to duplicate code for catching errors. Well, that time is now over with async/await!

const allErrorsAreDeclaredEqualInTheEyesOfAsyncAwait = async () => {
  try {
    const users = await db.getUsers
    const data = JSON.parse( users )
    console.log(data)
  }
  catch( err ){
    console.log('All errors are welcomed here! From promises or not, this catch is your catch.')
  }
}

Clean, concise and clean, while being concise. Good old try/catch can handle all the errors we can throw.

How high can you stack them errors?

As developers, if there is one thing we love, it is an infinite amount of functions in an error stack. It is probably not a huge deal, but more like a nice thing to know when you work with async/await. Check it out:

Now with async/await:

Ain't that much much more cleaner and easy to read?

Values in the middle

You probably wrote some code where you executed one operation and used that to execute a second one. Finally, you need those two values for the third and final operation. So, you may write something like that:

Let's look at how much better it is with async/await:

Do I need to say more?

Conclusion

Well, async/await is a very cool way to write asynchronous code in Javascript. You can try it out in Node.js because it is natively supported since version 7.6. Have fun!!

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content