JavaScript Async /await: The Good Part, Take-aways and How to Use

ES7 makes a major improvement in asynchronous programming of JavaScript by introducing async/await. It provides a way to access Resoruces asynchronously using synchronous code style without blocking the main thread. However, using it is a bit tricky. In this article we will explore async/await from different angles and show how to use them correctly and efficiently.

The benefits of async/await

The most important benefit async/await gives us is synchronous programming style. Let’s look at an example.

async/await
promise
await

The good news is not only readability,async/await has native browser support. As of today, all major browsers fully support asynchronous viewing.

Native support means you don’t have to transform code. More importantly, it helps with debugging. When you set a breakpoint at the function entry and skip the await line, you will see the debugger pause for a while during bookModel.fetchall () execution and then move to the next line.filter! This is much easier than the Promise case, where you have to set another breakpoint on the filter line.

async
getBooksByAuthorWithAwait()
promise
getBooksByAuthorWithAwait().then(...)
await getBooksByAuthorWithAwait()

getBooksByAuthorWithPromise
promise
null
.then()
async
null

Async/await may be misleading

I disagree with some articles that compare async/await with Promise and claim it is the next generation of asynchronous programming evolution in JavaScript. Async/await is an improvement, but it’s just syntactic sugar and it won’t completely change our programming style.

Essentially, the await function is still a promise. Before you can use await functions properly, you must know promises, and that in most cases you need to use promises and asynchronous functions together.

Considering the above example of getBooksByAuthorWithAwait () and getBooksByAuthorWithPromises () function. Notice that they are not only functionally identical, but also have exactly the same interface.

If direct call getBooksByAuthorWithAwait (), which means that returns a promise.

Well, that’s not a bad thing. It’s just that the name await makes it feel like “oh, this will convert an asynchronous function to a synchronous function” which is actually wrong.

The pit of Async/await

So what goes wrong with async/await? Here are some common situations.

It’s too order

While await can make your code look synchronous, remember that they are still asynchronous and care must be taken to avoid being too sequential.

  1. await bookModel.fetchAll()Will wait untilfetchAll()To return.
  2. thenawait authorModel.fetch(authorId)Will be called.Please note that.authorModel.fetch(authorId)It doesn’t depend onbookModel.fetchAll()In fact, they can be called in parallel! However, throughawaitUsed here, the two calls become sequential and the total execution time will be much longer than in the parallel version.

This is the right approach:

promise

await
promises

Error handling

With Promises, asynchronous functions have two possible return values: a parsed value and a rejected value. We can use.then() for normal cases and.catch() for special cases. However, async/await error handling can be tricky.

The try… catch

The most standard (and recommended) method is to use try… Catch statement. When an await is called, any rejected value is thrown as an exception. Here’s an example:

catch

  1. Handle the exception and return to normal. (notcatchBlock to use anyreturnStatement, which is equivalent to usingreturn undefined, is also a normal value.)
  2. Throw it if you want the caller to handle it. Ordinary error objects can be thrown directlythrow errorIn thepromiseAllowed in the chainasync getBooksByAuthorWithAwait()Function (that is, it can still be called like thisgetBooksByAuthorWithAwait().then(...) .catch(error => ...)); Or you can useErrorObject wrapping error, for examplethrow new Error(error)When this error is displayed in the console, the full stack trace is provided.
  3. Reject it, likereturn Promise.reject(error). This is equivalent tothrow errorIs not recommended.

Using a try… The benefits of catch are:

  • Simple, traditional. As long as you have experience with other languages such as Java or C++, there should be no difficulty.
  • If you don’t need to perform error handling at each step, you can still do it in onetry... catchMultiple packages in a blockawaitThe call handles the error in one place.

There is a drawback to this approach. Due to try… Catch will catch every exception in a block, so it will catch some exceptions that promises would not normally catch. Consider this example:

ReferenceError: cb is not defined
console.log()
BookModel

Causes the function to return two values

Another approach to error handling is inspired by the Go language. It allows asynchronous functions to return errors and results. For more information, see this blog post: How to write Async await without try-catch blocks in Javascript

In short, you can use await functions like this:

Use. Catch

The final method we’ll cover here is to continue using.catch().

Recall the functionality of await: It will wait for a promise to finish its work. Recall that promise.catch() will also be a promise, so we can write error handling like this:

  1. It is apromisesandawaitA mixture of functions. You still need to knowpromisesHow does it work?
  2. Error handling takes place before the normal path, which is not intuitive.

conclusion

The keyword async/await introduced in ES7 is certainly an improvement over asynchronous programming in JavaScript. It makes code easier to read and debug. However, in order to use them properly, promises must be fully understood, because they are nothing more than syntactic sugar, and the underlying technology is still promises.