Async, Await, Another Way

Patrick McClernan
Tech at Power
Published in
4 min readAug 10, 2020

--

In writing JavaScript, you will occasionally have to write asynchronous code. This was originally handled by callbacks. When you have to make several callbacks in a row, you can end up with some deeply nested code that becomes hard to read. Some recent JavaScript updates provide new functionality that handle this type of asynchronous code more cleanly.

Promises were introduced in 2015 in ES6 and allowed these deeply nested callbacks to be expressed in a cleaner way. Instead of nesting deeper for each consecutive asynchronous call, you could now chain promises using the .then method on the them. So you still have some boilerplate code to chain everything together, but your code is less nested.

Logging info from an async request with callbacks vs promises

As of 2017 with ES8, two new keywords were added that offer a new way to handle these types of situations. Functions can now be prefaced with the keyword async. Async functions are guaranteed to return a promise. You can return an object from Promise.resolve() yourself, or your return value will automatically be wrapped in a Promise if you don’t.

On its own, this doesn’t provide you with much. But that’s where the second keyword comes in - await. It can only be used in the body of an async function and will pause execution to wait for a promise to resolve. You can almost think of await as wrapping the rest of the function inside of the .then of a promise chain. The rest of the code after it will wait to run until the awaited value is available.

Here’s an example where we fetch from a URL, parse the response as JSON, and log the JSON to the console. The code on the left and right do the same thing.

Using fetch vs using an async function

The await keyword goes in front of a promise, or an expression that returns a promise. This means you can await any async function, in addition to anything else that already returns a promise. In the example above, await is used before the fetch call, assigning the resp constant the value returned from the fetch call. Then the value returned from the json method on that response to store the value we want to print. Both of these lines run asynchronously, and we don’t need to use any callbacks.

Using await pauses the execution of an async function until the promise it’s waiting for resolves. This is similar to how .then doesn’t call the provided callback until the resolved value is available.

If you invoke an async function, it will execute synchronously until it hits an await keyword. As soon as it does, the execution in the function pauses and the code after the function call runs, back in the original execution context. Then, once the promise is resolved, the async function will continue where it had paused.

Here’s an example. We define an async function that uses await once. We have a log before and after the function gets called. Inside the function, we have a log before and after the line that uses await. Let’s see what order the messages get logged:

Here it is — the actual order the messages get logged. The log from before the function fires first, as expected. Then, synchronously, the log before the await fires, as it would in a normal function call. Then, due to the await keyword, the execution is paused inside the function, and the code after the function call continues running to completion. Then, the promise has a chance to resolve and the final line of the async function runs.

As you can see, this allows you to write your async code in a style that looks more synchronous. The execution jumps around similarly to how it would using .then, but the values returned can be stored directly in a variable instead of being passed to a callback in the next then call.

This alternate approach offers another way to write asynchronous code in a more concise style. Your asynchronous code can be written in a style that more closely resembles regular, synchronous code. This allows you to write and reason about both types of code in the same way. Try it out next time you need to deal with promises!

This post is written by a Power Code Academy Student Developer.

--

--