DEV Community

Cover image for Async & Await in JS
Vigneshwaran V
Vigneshwaran V

Posted on

Async & Await in JS

async and await are JavaScript keywords that provide a cleaner, more readable way to handle asynchronous operations without relying on complex Promise chains (.then() and .catch()). They make asynchronous code look and behave more like traditional synchronous code, which simplifies writing and maintaining your applications.
Async
async (Asynchronous): Placed before a function declaration to turn it into an asynchronous function. An async function always returns a Promise. If you return a normal value, JavaScript automatically wraps it inside a resolved Promise.
Await
await (Wait for resolution): Used inside an async function to pause code execution until a Promise resolves or rejects. It allows you to assign the resolved value of a Promise directly to a variable.

We use async/await to make asynchronous code look and behave more like normal synchronous code, making it easier to read and maintain.

  • We use async/await to execute multiple dependent asynchronous operations in a simple top-to-bottom manner. It allows us to wait for the result of one Promise before using it in the next step, making the code easier to read and manage.

Without async/await (using Promise)

   <script>
        function getUserById(id){
            console.log("Got User id: ",id);

            return new Promise((resolve,rejcet)=>{
                setTimeout(()=>{
                    resolve({id:id, name: 'vicky'});
                },1000)
            })
        }

        function getSubcriptions(id){
            console.log("Got User Subscriptions for: ",id);

            return new Promise((resolve, reject) => {
                setTimeout(()=>{
                    resolve([
                        {id:1, title:'netfilx'},
                        {id:2, title:'hotstar'},
                        {id:3, title:'AmazonPrime'}
                    ]);
                },2000)
            })
        }

        function calculateTotal(subcriptions){
            console.log("Subscriptions: ",subcriptions);

            return new Promise((resolve, reject) => {
                setTimeout(()=>{
                    resolve(subcriptions.length * 100);
                },3000)
            })
        }

        getUserById(1)
        .then(getSubcriptions)
        .then(calculateTotal)
        .then(cost =>{
            console.log("total Cost: ",cost);
        })
    </script>
Enter fullscreen mode Exit fullscreen mode

Ouput

Got User id:  1
promise.html:22 Got User Subscriptions for:  {id: 1, name: 'vicky'}
promise.html:36 Subscriptions:  (3) [{…}, {…}, {…}]
promise.html:49 total Cost:  300
Enter fullscreen mode Exit fullscreen mode

With async/await (using Promise)

    <script>
        function getUserById(id) {
            console.log("Got User id: ", id);

            return new Promise((resolve, rejcet) => {
                setTimeout(() => {
                    resolve({ id: id, name: 'vicky' });
                }, 1000)
            })
        }

        function getSubcriptions(id) {
            console.log("Got User Subscriptions for: ", id);

            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve([
                        { id: 1, title: 'netfilx' },
                        { id: 2, title: 'hotstar' },
                        { id: 3, title: 'AmazonPrime' }
                    ]);
                }, 2000)
            })
        }

        function calculateTotal(subcriptions) {
            console.log("Subscriptions: ", subcriptions);

            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(subcriptions.length * 100);
                }, 3000)
            })
        }

        async function displayTotalCost() {
            try {
                //call the promise one by one 
                const userInfo = await getUserById(1);
                const subcriptions = await getSubcriptions(userInfo);
                const total = await calculateTotal(subcriptions);

                console.log("total Cost: ", total);
                console.log("Everything is Fetched...");
            } catch (error) {
                console.error("Catch-block: ",error);
            }

        }

        displayTotalCost();
    </script>
Enter fullscreen mode Exit fullscreen mode

Output

Got User id:  1
promise_With_Async.html:24 Got User Subscriptions for:  {id: 1, name: 'vicky'}
promise_With_Async.html:38 Subscriptions:  (3) [{…}, {…}, {…}]
promise_With_Async.html:54 total Cost:  300
promise_With_Async.html:55 Everything is Fetched...
Enter fullscreen mode Exit fullscreen mode

In our example:

  • Get the user details.

  • Get that user's subscriptions.

  • Calculate the total cost using those subscriptions.

  • Display the result.
    Each step depends on the previous step, so await is useful.

Why use async/await here?

1. Better Readability
Without async/await

getUserById(1)
    .then(userInfo => {
        return getSubcriptions(userInfo);
    })
    .then(subscriptions => {
        return calculateTotal(subscriptions);
    })
    .then(total => {
        console.log(total);
    });
Enter fullscreen mode Exit fullscreen mode

With async/await

const userInfo = await getUserById(1);
const subscriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subscriptions);
Enter fullscreen mode Exit fullscreen mode

2. Handles Dependent Operations Easily
Your operations depend on each other:

User
  ↓
Subscriptions
  ↓
Total Cost
Enter fullscreen mode Exit fullscreen mode

You cannot calculate the total before getting subscriptions.
await naturally enforces this order.

const userInfo = await getUserById(1);
const subscriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subscriptions);
Enter fullscreen mode Exit fullscreen mode

3. Easier Error Handling
A single try...catch can handle errors from all three Promises.

try {
    const userInfo = await getUserById(1);
    const subscriptions = await getSubcriptions(userInfo);
    const total = await calculateTotal(subscriptions);
} catch(error) {
    console.log(error);
}
Enter fullscreen mode Exit fullscreen mode

Without async/await, you'd usually handle errors with .catch().
4. Code Looks Synchronous
Although each function takes time:

getUserById       -> 1 second
getSubcriptions  -> 2 seconds
calculateTotal   -> 3 seconds
Enter fullscreen mode Exit fullscreen mode

the code looks like:

step1();
step2();
step3();
Enter fullscreen mode Exit fullscreen mode

which is easier for us to understand.


In this example, async/await is used because each operation depends on the result of the previous operation. It makes the asynchronous workflow (Get User → Get Subscriptions → Calculate Total) easier to read, maintain, and handle errors compared to Promise chaining with .then().


References
https://www.geeksforgeeks.org/javascript/async-await-function-in-javascript/
https://www.w3schools.com/js/js_async_await.asp

Top comments (0)