JavaScript

Understand Async/Await functions in JavaScript | Explained with Examples

The keyword async is used to convert a function into an async function while await keyword is only useable inside an async function. Async and await are used for asynchronous execution of the program and implement a promise-driven functionality to the code.

Async keyword when used from defining a function makes the function return a Promise, while await function makes the async function wait for a promise to be returned inside it. To understand the usage of async and await functions you need to have a keen understanding of how promises work in JavaScript.

Async and await is an advanced-level JavaScript concept, that is why we are going to learn it through various examples and understand it by going through the example line by line.

Sequential Execution in JavaScript

JavaScript is a sequentially executed or we can say single-threaded scripting language. The code is invoked line by line in a procedural fashion.

Consider the lines of code typed below:

function hello() {
  console.log("Hello World");
  linuxHint();
}

function linuxHint() {
  console.log("Tutorial by linuxHint");
}

console.log("Code is executed in the sequence that it is invoked");
hello();

Observe the output on the console as:

As you can see, the functions or lines invoked first were always finished first. The reason for showing you a simple example like this was to make you notice when the execution sequence will change with async await and promises.

Async/ Await in action

Consider a simple function that returns some text, like:

function getUsers() {
  console.log("Inside the getUsers function");
  return "Users";
}

console.log("Start of the code");
var list = getUsers();
console.log(list);

console.log("End of the code");

The output of the following code is:

As we can see the function returned as the string that says, users. Let’s try putting the keyword async before function definition as:

async function getUsers() {
  console.log("Inside the getUsers function");
  return "Users";
}

Now, on your console you will see that this time around the function returned a promise that had the status “fulfilled”:

But in cases where you are fetching some data from some REST API or any WEB API, this promise will change multiple states, from pending to fulfilled/rejected. In such cases, we wait for the return of the promise’s result by using the await keyword.

For this, we are going to use the Fetch API and fetch the information about users from the “api.github/users” with the following lines of code:

async function getUsers() {
  console.log("Inside the getUsers function");
  const response = await fetch("https://api.github.com/users");
  console.log("API RESPONDED, USERS RECEIVED");

  const users = await response.json();
  console.log("CONVERTED JSON");
  return users;
}

There is a lot of stuff to be explained here:

  • When a new variable is initialized with this function, the first line will be executed and text will be printed onto the console.
  • When the code reaches the keyword await it will check whether the promise is fulfilled or pending, if it is in the pending state then it will exit this function and execute other parts of the code.
  • After executing other parts of the code, it will come back inside the function at the first await keyword and recheck the status of the promise.
  • Upon receiving a fulfilled/reject status it will execute the next line which is console.log().
  • In the next line, response.json is also a promise, it will check for its status and upon pending status, it will exit the function and execute the other parts of the code.
  • After all the other code is executed, the pointer will come back in the function, check the status of response.json, and on fulfilled/rejected status it will execute the next line.

In this way, this whole program will exit the normal sequential execution and implement an asynchronous execution of the code by using promises and async/await keywords.

The complete code snippet is as:

async function getUsers() {
  console.log("Inside the getUsers function");
  const response = await fetch("https://api.github.com/users");
  console.log("API RESPONDED, USERS RECEIVED");

  const users = await response.json();
  console.log("CONVERTED JSON");
  return users;
}
console.log("Code starts");
var list = getUsers();
console.log("Variable list created");
console.log(list);
list.then((user) => console.log(user));
console.log("Last line of the code");

Note: The line “list.then((user) => console.log(user));” will not be executed until the function getUsers deals with all the promises and returns the value, even here the sequential execution will alter.

Now, if you run this program as a script of an HTML file, you will see the following output on your console:

Examine the output closely and you will notice the flow of execution as:

  • Code starts and the variable is declared on the function.
  • The pointer goes inside the function, prints the first line, sees the await keyword, leaves the function, and returns a pending promise to the variable “list” that we just created.
  • Executes other parts of the code (that is why you can see “last line of the code”) while waiting for the promise in the await.
  • Sees the line list.then() but it will not be executed until the function getUsers returns a promise with a status solved/rejected.
  • Goes back inside the function, API responds, creates a list of users, and converts it into JSON.
  • The status of the promises returned by the async function getUsers changes to fulfilled and the list.then() line executed and we get the JSON data printed onto the console.

That is how you alter sequential execution and implement asynchronous execution

Conclusion

Async and await keywords are used to implement asynchronous execution of the JavaScript code with the help of promises. Async keyword when used before the declaration of a function converts that function into an async function and its return type changes to a promise. While await is a keyword that waits for a promise to be received inside an async function. Async/await help us write promises in a much nicer, and tidy way that is more readable and understandable.

About the author

Shehroz Azam

A Javascript Developer & Linux enthusiast with 4 years of industrial experience and proven know-how to combine creative and usability viewpoints resulting in world-class web applications. I have experience working with Vue, React & Node.js & currently working on article writing and video creation.