Async/Await in Javascript

·

4 min read

Async/Await in Javascript

What is synchronous JavaScript?

In a synchronous system, tasks are completed one after another. Think if you have only one hand and you need to complete 10 assignments So, you have to complete one assignment at a time.

Well, JavaScript is by default Synchronous, it runs one line after another.

console.log(" I ");
console.log(" eat ");
console.log(" cupcake ");

// output 
// I 
// eat
// cupcake

What is Asynchronous JavaScript?

In this system, tasks are completed independently. For example, we have 10 tasks, and we have 10 hands. So, each hand can do each task independently and at the same time. None of them is waiting for any of the others.

console.log("I");

// This will be shown after 2 seconds

setTimeout(()=>{
  console.log("eat");
},2000)

console.log("cupcake")

// output
// I
// cupcake
// eat

Let's start by making a cupcake for our customers. Our shop will have two parts:

  • store-room to store all ingredients.

  • the kitchen where we will prepare our orders.

let's make out store-room first.

let storeRoom = {
    fruits : ["strawberry", "grapes", "banana", "apple"],
    frosting : ["cream", "jelly", "candy"],
    toppings : ["chocolate", "sprinkle"],
 };

Now, the entire process depends on order, once we have an order, we will start our production. so production depends on the order. Let's convert this into a function.

let order = (start_Production) => {
console.log("got order, start production");
start_Production();
}

let production = () => {
console.log("Production has started")
}

order(production) 

/* output -- 
got order, start production
Production has started
*/

Now, let's describe our production phase in detail.

  1. place order -> 2 seconds

  2. cut the fruit -> 2 seconds

  3. prepare a base -> 3 seconds

  4. start a machine -> 2 seconds

  5. decorate with frosting -> 2 seconds

  6. add topping -> 3 seconds

  7. serve cupcake -> 2 seconds

let order = (fruit_name, start_Production) => {
    console.log("order taken")
    setTimeout(()=> {
        console.log(`${storeRoom.fruits[fruit_name]} was selected`);
        start_Production(fruit_name);
    },2000)
}
order(0,production);

Now, let's start by writing our production function.

let production = (fruit_name) =>{
  setTimeout(()=>{
    console.log("production has started")
    setTimeout(()=>{
        console.log("fruits has been chopped")
    },2000)
  },0000)
};

/* output -- 
order taken
------( 2 second hold )------
strawberry was selected
production has started
------( 2 second hold )------
fruits has been chopped
*/

To complete the whole process, it will take a lot of setTimeout functions.

let production = (fruit_name) =>{

  setTimeout(()=>{
    console.log("production has started")
    setTimeout(()=>{
      console.log("The fruit has been chopped")
      setTimeout(()=>{
        console.log(`base has been prepaed with ${storeRoom.fruits[fruit_name]}`)
        setTimeout(()=>{
          console.log("start the machine")
          setTimeout(()=>{
            console.log(`decored with frosting ${storeRoom.frosting[1]}`)
            setTimeout(()=>{
              console.log(`${storeRoom.toppings[0]} as toppings`)
              setTimeout(()=>{
                console.log("serve cupCake")
              },2000)
            },3000)
          },2000)
        },2000)
      },3000)
    },2000)
  },0000)

};

Did you notice anything? Our code is increasing vertically and it isn't very clear. This is called callback hell.

Now, we and solve this with two things. 1st is Promise and 2nd is async/await.

let's create a variable and make it an entry point for our code.

let is_shop_open = true;

Now, let's make our order function as Promise. We will also pass on two arguments.

let order = (time, work) => {
    return new Promise((resolve, reject) => {
        if(is_shop_open){
            setTimeout(()=>{
        resolve( work() )
       }, time)
        }
        else{
            reject("show is closed")
        }
    })
}

So, now lets we define what we need to do when the first task is complete using the .then handler.

order(2000, console.log(`${storeRoom.fruits[0]} was selected`))
.then(()=>{
    return order(0000,  console.log("production has started"))
})
.then(()=>{
    return order(2000,  console.log("The fruit has been chopped"))
})
.then(()=>{
    return order(3000,  console.log(`base has been prepaed with ${storeRoom.fruits[fruit_name]}`))
})
.then(()=>{
    return order(2000,  console.log("start the machine"))
})
.then(()=>{
    return order(2000,  console.log(`decored with frosting ${storeRoom.frosting[1]}`))
})
.then(()=>{
    return order(3000,  console.log(`${storeRoom.toppings[0]} as toppings`))
})
.then(()=>{
    return order(2000,  console.log("serve cupCake"))
})
.catch(()=>{
  console.log("Customer left")
})

and the output will be the same! Here, for the error handling, we are adding a catch() method at the end of the code, it will be run whenever there is an error.

we have another way to handle promises. That's Aysnc/await. All you have to do is write the word async before any regular function and it becomes a promise.

function time(ms) {

   return new Promise( (resolve, reject) => {

      if(is_shop_open){
         setTimeout(resolve,ms);
      }

      else{
         reject(console.log("Shop is closed"))
      }
    });
}
async function kitchen(){
    try{
    await time(2000)
    console.log(`${stocks.Fruits[0]} was selected`)

    await time(0000)
    console.log("production has started")

    await time(2000)
    console.log("The fruit has been chopped")

    await time(3000)
    console.log(`base has been prepaed with ${storeRoom.fruits[fruit_name]}`)

    await time(2000)
    console.log("start the machine")

    await time(2000)
    console.log(`decored with frosting ${storeRoom.frosting[1]}`)

    await time(3000)
    console.log(`${storeRoom.toppings[0]} as toppings`)

    await time(2000)
    console.log("Serve Cupcake")
    }

    catch(error){
     console.log("customer left")
    }
}

In async/await, we handle the try-catch block to handle the errors. The keyword await makes JavaScript wait until a promise settles and returns its result.

So now, we will again get the same results as we got for callbacks and promises. Async/Await makes code easier to read and handle it.

Whenever we are using the async function, it's nice to put code into try and catch block. await will not work without the async function.