Async/await in JavaScript

Async/await is an extension of promise. We use async keyword with a function to represent that the function is asynchronous. The async function returns a promise. It is also possible to use await keyword inside a async function.

Javascript async keyword:
Syntax:
async function name(parameter1, parameter2, ...paramaterN) {
    // statements
}

name – name of function

parameter- parameter that are passed

Example:
// async function example

async function f() {
    console.log('Async function.');
    return Promise.resolve(1);
}
Output:

Async function.

Since async function returns a promise we can use chaining method then()

Async with promise chaining:
async function f() {
    console.log('Async function.');
    return Promise.resolve(1);
}

f().then(function(result) {
    console.log(result)
});
Output:

Async function.

1

In the example first f() function is resolved and then function gets executed.

JavaScript await keyword:

await keyword is used inside the async function to wait for asynchronous operation.

Syntax:

let result = await promise;

await pauses the asynchronous function till the promise returns a resolved or rejected value.

// a promise
let promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
    resolve('Promise resolved')}, 4000); 
});

// async function
async function asyncFunc() {

    // wait until the promise resolves 
    let result = await promise; 

    console.log(result);
    console.log('Hello');
}

// calling the async function
asyncFunc();
Output:

Promise resolved

Hello

Here first a promise object is created and it gets resolved after 4000 milliseconds. The async function waits for promise to resolve or reject and returns hello only after promise is complete.

The same program without await will print hello before resolving promise.

The async function helps to execute asynchronous methods in a synchronous way. This is helpful for multiple promises in a program.

let promise1; 
let promise2;
let promise3;

async function asyncFunc() {
    let result1 = await promise1;
    let result2 = await promise2;
    let result3 = await promise3;

    console.log(result1);
    console.log(result1);
    console.log(result1);
}
Error handling:
In async function we can use catch method to catch the errors.
asyncFunc().catch(
    // catch error and do something
)
We can also use try/catch,
// a promise
let promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
    resolve('Promise resolved')}, 4000); 
});

// async function
async function asyncFunc() {
    try {
        // wait until the promise resolves 
        let result = await promise; 

        console.log(result);
    }   

    catch(error) {
        console.log(error);
    }
}

// calling the async function
asyncFunc(); // Promise resolved

Output:

Promise resolved

Async/await is helpful in error handling, debugging and makes the code readable.

Supported Browsers: 
  • Google Chrome 55 and above
  • Firefox 52 and above
  • Apple Safari 10.1 and above
  • Opera 42 and above
  • Edge 14 and above

Promise in JavaScript

JavaScript is a single-threaded or synchronous programming language but with promises we can make it look like multi-threaded or asynchronous programming language. Imagine a function waiting for a network request to complete which takes more time. Meanwhile entire execution freezes at that time we need asynchronous operations. Prior to promises, events and callback functions are used. But events and callback functions create callback hell and can lead to unmanageable code. It is not easy to handle multiple callbacks at a time. Events are not good in asynchronous operations. So obviously, promise became the best choice for handling asynchronous operations.

In JavaScript, promise is a way of handling asynchronous operations. It is an object that holds the future value of an asynchronous operations. It is helpful in finding out whether a asynchronous operation is successfully completed or not.

Benefits of Promises:

  • Improves code readability.
  • Better at handling multiple callback functions at the same time and avoiding callback hell situation.
  • Better control flow in asynchronous logic
  • Improves error handling

Difference between promises and event handlers:

  • A promise can never fail or succeed twice. It can be only once.
  • A promise can never switch from success to fail or fail to success.
Promise has three states:
  • Pending
  • Fulfilled
  • Rejected

Pending – Initial state. A promise starts here.

Fulfilled – If operation was successful ends in fulfilled state.

Rejected – If operation was fail ends in rejected state.

A promise is settled if it is either fulfilled or rejected but not pending.

Create a promise:

To create a promise we use constructor Promise()

let promise = new Promise(function(resolve,reject){
	//do something
});

Promise() constructor takes function as an argument. This function accepts two functions resolve() and reject(). If promise is successful returns resolve() function and by failure returns reject() function.

Example:
const count = true;

let countVal = new Promise(function (resolve, reject) {
    if (count) {
        resolve("There is a count value.");
    } else {
        reject("There is no count value");
    }
});

console.log(countVal);
Output:

Promise { ‘There is a count value.’ }

In above example promise is resolved if count is true.

JavaScript Promise chaining:

Promises are useful in handling more than one asynchronous task one after another. For that we have promise chaining. We use then(), catch() and finally() methods.

JavaScript then() method:

then() method is used with callback when promise is successfully fulfilled or resolved.

Syntax:
.then(function(result){
        //handle success
    }, function(error){
        //handle error
    })
Example:
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); 

}).then(function(result) { 

  console.log(result); 
  return result * 3;

}).then(function(result) { 

  console.log(result); 
  return result * 4;

}).then(function(result) {

  console.log(result); 
  return result * 6;
});
Output:

1

3

12

Here all operations returns the result to the next then on the chain and this continues till last element and final result is returned.

JavaScript catch() method:

catch() is used when a promise is rejected or if an error occurs. It is used as error handler whenever at any step there is chance of getting error.

Syntax:
.catch(function(error){
        //handle error
    })
Example:
// returns a promise
let countValue = new Promise(function (resolve, reject) {
   reject('Promise rejected'); 
});

// executes when promise is resolved successfully
countValue.then(
    function successValue(result) {
        console.log(result);
    },
 )

// executes if there is an error
.catch(
    function errorValue(result) {
        console.log(result);
    }
);
Output:

Promise rejected.

MethodDescription
Promise.all()Waits for all promises to be resolved or any one to be rejected
Promise.allSettled()Waits until all promises are settled
Promise.any()Returns the promise value as soon as any one of the promises is fulfilled
Promise.race()Wait until any of the promises is resolved or rejected
Promise.reject()Returns a new Promise object that is rejected for the given reason
Promise.resolve()Returns a new Promise object that is resolved with the given value
catch()Appends the rejection handler callback
then()Appends the resolved handler callback
finally()Appends a handler to the promise