Async and await in Javascript.

The concept of async and await in javascript.

The concept of async and await is a very useful tool when it comes to asynchronous codes. It is a concept that makes writing promise-based code easier.

What is a promise?

Though the concept of the promise is one of the prerequisites to understanding how async and await keywords works, this article will like to refresh our memory about promise. The first step in understanding async and await is to understand its very foundation which is promise. According to the web docs on javascript, a promise is an object that returns a value upon the completion or failure of an asynchronous method or function (an asynchronous function will be explained later on). The main purpose of a promise is to make an asynchronous function return values like the synchronous function. A promise has three states:

  • pending: the initial state, the operation has not been fulfilled or rejected yet

  • fulfilled: meaning the operation was completed

  • rejected: meaning the operation failed

A promise is either resolved and returns a value or it's rejected due to a reason. More information on a promise is here.

What is an asynchronous function?

Javascript is a synchronous language which means the instructions are executed one after the other. Look at the code block below:

let a=3
let b=4
let result=a+b
console.log(result)

The code block above shows the instructions are executed one after the other i.e. it's a synchronous function. This method however has some limitations for example: if we are to fetch some data at multiple points in our code, using the synchronous method becomes a problem; however, this problem can be addressed by using the asynchronous method. An asynchronous method can be thought of as the opposite of the synchronous method meaning the instructions are not executed one after the other and the code can start now and finish later. The setTimeout function in javascript and promise are asynchronous methods.

let name="Sicario"
setTimeout(function(){
console.log("asynchronous"
},2000)
console.log("synchronous")
console.log(name)

From the code block above, the values logged to the console will follow this sequence:

  1. synchronous

  2. Sicario

  3. asynchronous

It follows this sequence because the setTimeout function is an asynchronous function so according to the code after 2000milliseconds(2 seconds) the code in the setTimeout function will be executed. Now that we know the differences between synchronous and asynchronous methods, we move to the async and await keywords.

Prerequisites

To follow up with this concept of async and await explained in this article you must have at least a basic understanding of a few things, which include:

  • Functions

  • Arrow function expressions.

  • Classes.

  • Objects.

  • Promise.

async and await keyword

For ease of comprehension, the async keyword can be addressed as the abbreviation of "asynchronous"; therefore, when will we see the async keyword before a function it makes the function asynchronous.

async function name(params){
statemets}
// name= name of the function
// params= the parameters of the function
// statemets = what the function is expected to do.

The code block above shows how to use the async keyword to make a function asynchronous.

In the case of the await keyword, as the name suggests, this keyword makes the function wait i.e suspends the execution of the function and resumes with the outcome (either resolved or rejected) of a promise. The await keyword can only be used with the async keyword, else we get an error like this:

async function sum(a,b){
  let promise =new Promise((resolve,reject)=>{
  setTimeout(()=>{resolve(a+b)},2000)
})
let result= await promise//result is the summation of a+b
console.log(result)// the result will be logged to the console
}
sum(2,8)// we call the sum function

When you look at the code block above, imagine this in your head: when the execution of the code gets to the line which the await keyword is used, the await keyword behaves like a pause button, meaning the execution will pause at the line the await keyword is used which will give time for the function to -give the function time to get some data- calculate the sum of a and b as shown above. When the outcome of the sum has been calculated, the outcome of the code whether resolved or rejected will act as the play button for the execution of the code to continue. Let's look at another example:

async function displayName(){ //"async" makes the function asynchronous
let mypromise=new Promise((resolve,reject)=>{
resolve("My name is Sicario");// result of the resolved promise
});
let myname=await mypromise; // wait till the promise is resolved
alert(myname);
}
displayName();

How to infuse async and await into your code.

One of the challenges faced by a lot of junior developers is how to use a newly learned concept in a project or while practicing. Now that you understand what async and await is, this section will give some examples of ways we can use async and await. Some of the ways are:

  • Fetching data from an endpoint.

  • Error handling.

  • Methods for class and objects.

Fetching data from an endpoint

Fetching data from an endpoint or some other source, the concept of async and await is quite common in this case. Let's explain this with some blocks of codes:

async function myfetch(url){
 try{
    let the_fetch=await fetch(url) //fetching the data from an endpoint
    let result=await the_fetch.json() // converting the data to json
    console.log(result)
}
catch(err){
 console.log(err)//logging the error to the console
}
 }

 myfetch("http://swapi.dev/api/planets/1")// calling the function

From the code above, the concept of async and await is quite clear; however, we can decide not to use try...catch and use throw for the error message, the code will look like this:

async function myfetch(url){
    let the_fetch=await fetch(url) 
    if(the_fetch.ok){
       let result=await the_fetch.json() 
       console.log(result)
   }
   else{
    throw new Error("Error occured")// to throw an error in case of any
   }
    }
 myfetch("http://swapi.dev/api/planets/1")// calling the function

The endpoint used in the code is the Starwars movie api.

Error handling

The code block above already shows some ways to handle errors in asynchronous functions. Some of the common ways to handle errors in asynchronous functions include: try...catch block and the throw keyword. We can use these two methods of error handling in combination with async and await

Let's take a look at the try...catch block, as the name implies you try some line of code and then you catch an error if any should occur, that's all to it.

async function Addition(a,b){

try{
let add=new Promise ((resolve,reject)=>{
  resolve(a+b)
})
let result=await add
console.log(result)
}
catch(err){
console.log(err)
}
}
Addition(3,7)

So when you run this code, the code within the "result" variable will wait for the code assigned to the "add" variable to be executed since we use the await keyword, and if we have any error in the code the catch block is watching out for that.

Let's take a look at one of the codes above one more time:

async function myfetch(url){
    let the_fetch=await fetch(url) 
    if(the_fetch.ok){
       let result=await the_fetch.json() 
       console.log(result)
   }
   else{
    throw new Error("Error occured")
   }
    }
 myfetch("http://swapi.dev/api/planets/1")

in this case, we use the throw keyword to throw out error messages instead of the catch block, and we can hardcode whatever error message we want.

Methods in classes and objects

When we want to define a method in a class or an object, using the async and await keyword the syntax will look like this:

class Success {
  async wait(){
     let response= new Promise((resolve,reject)=>{
      resolve("Successful")
     })
     let result=await response
     console.log(result)// "Successful" gets logged to the console
  }
 }
 new Success()
 .wait()// calls the method in the class

You can see in the code block above, We prepend the function with the async keyword and await keyword waits for the value of the promise. This is identical to the way we use async and await keywords to define functions outside of classes or objects.

Conclusion

Let's go over the main functions of the two keywords.

async:

  • Convert the function to an asynchronous function(by prepending the function with the async keyword).

  • Allows the await keyword to be used within the function.

  • Allows the function to be able to return a promise.

await:

  • It waits for a promise to be resolved and returns the result; otherwise, if the promise is rejected it returns an error.

The combination of the async and await keyword makes it easy to write asynchronous and promise based code; however, the use of async and await keyword is not a total replacement for promise rather it's a concept based on how promise works.