Async/Await in Asynchronous Javascript

To handle asynchronous Javascript, callbacks were first used but it had major cons like callback hell. Then came about promises to try to improve things. However, .then chains can also get nested and confusing.
So now, we have async/await, which was introduced in NodeJS 7.6 and is currently supported in all modern browsers.

The async/await syntax allows you to work with promises in a cleaner fashion. It makes asynchronous code easier to read and understand. However, it is important to note that async/await is actually just syntax sugar built on top of promises. It cannot be used with plain callbacks or node callbacks.

Async/await is similar to promises in that they are non-blocking (since they built on top of promises) and it makes asynchronous code look and behave a more like synchronous code. This is an important advantage over pure promises.


Using the word “async” before a function means that the function will always return a promise. Return values are wrapped in a promise automatically.

For example, this function returns a resolved promise with the result of hello, as shown below:

async function asyncFn() {
return "I love 🍰";

asyncFn().then(alert); // I love 🍰
Alert message when executing the code block above in the google chrome console

…or we can also explicitly return a promise, that would produce a similar result:

async function asyncFn() {
return Promise.resolve("I love 🍰");

asyncFn().then(alert); // I love 🍰

So, async ensures that the function always returns a promise and hence we can use the .then() method to display the alert output as hello.


Await works only inside async functions.

await will not work in top-level code. For example, this will not work:

// syntax error in top-level codelet response = await fetch('/users.json'); 
let users = await response.json();

To make it work, we can wrap it into an Immediately-invoked Function Expression (IIFE), like this:

(async () => {
let response = await fetch('/users.json');
let users = await response.json();

Also, even if it’s not top level code, e.g. using await in a function like in the below code block, it will still throw a syntax error as the function is not prefixed with the async keyword.

function asyncFn() {
let promise = Promise.resolve("hello").then(console.log);
let result = await promise; // Syntax error
Await NOT used in an async function: Syntax error

To fix that, we have to add the async key word in order to use await properly:

async function asyncFn() {
let promise = Promise.resolve("hello").then(console.log);
let result = await promise;

Await being used in an async function: no syntax error and we see the “hello” console log message being logged

The await keyword literally ensures that JavaScript waits until the promise settles (fulfilled or rejected). It is a cleaner syntax of getting the promise result compared to promise.then()


Add theasync keyword before a function and:

  1. It makes it always return a promise.
  2. Allows us to use await in that function

The await keyword before a promise makes JavaScript wait until that promise settles, and then:

  1. If there is an error, the exception is generated
  2. Otherwise, it returns the result.

Async/await is a great feature that has been added to JavaScript in the past few years. When usingasync/await , we rarely need to write promise.then().catch(), but we should still be cognizant that the foundation of async functions is Promises.

Having a good understanding of the latter is crucial for understanding the former. This is especially so when you have to work with legacy/inherited code that isn’t based on Promises with async functions, where you may have no choice but to use Promises directly.


Software Developer at @thoughtworks | Marathon Runner | Ex-Pharmacist Writing on Coding, Technology and Running

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store