JavaScript - How to use async & await?

async and await are used to make asynchronous call to synchronous. async could be used before a function.

Technically it is possible to use async on any function to make it asynchronous. It automatically wraps the return to a Promise. Any error thrown inside the method would also be wrapped inside a Promise.

Unnecessary use of async

async function square(m) {
    return m * m;
}
// print Promise { 16 }
console.log(square(4));

The function square is not having any await. The Promise return would resolve immediately and async gives no benefit. Executing above code would print Promise { 16 }.

Most useful scenario for async & await

Take the slightly modified code as an example. An await has been placed to simulate delay of 0 millisecond.

const delayForMs 
    = (forMilliseconds) 
        => new Promise(resp 
            => setTimeout(resp, forMilliseconds));

async function square(m) {
    // To use await the function must be async
    await delayForMs(0);
    return m;
}
const squareOf4 = square(4);
// Prints Promise { <pending> }
console.log(squareOf4);

// Use then and catch 
// to handle resolve and reject cases
squareOf4
    .then((val) => console.log(val))
    .catch(err => console.log(err));

Using await to make square synchronous

const delayForMs 
    = (forMilliseconds) 
        => new Promise(resp 
            => setTimeout(resp, forMilliseconds));

async function square(m) {
    await delayForMs(2000);
    return m;
}

async function getSquare(num) {
    const squareOfNum = square(num);
    let squareOfNumValue = await squareOfNum;
    // this log statement prints 16
    // The execution waits for above to complete
    console.log(squareOfNumValue);
}
getSquare(4);

It can be seen that above example is nesting async functions. It is totally fine to nest async functions to any level.

Use with thenable class

A class implementing then method is called thenable class. Such a class can have attributes and functions with any name.

class ThenableGreeter {
    constructor(name) {
        this.name = name;
    }
    then(resolve, reject) {
        // resolve with Greet after 2000ms
        setTimeout(() 
            => resolve(`Hello ${this.name}`), 2000);
    }
}

async function getGreet() {
    let result = await new ThenableGreeter('GreetGetter');
    // prints Hello GreetGetter
    console.log(result);
}

getGreet();

It can be noticed that an await is being used on a class constructor.

Comments