Skip to content

Latest commit

 

History

History
175 lines (122 loc) · 5.78 KB

File metadata and controls

175 lines (122 loc) · 5.78 KB

Introduction

Async function always return Promises

Async functions allow you to write promise-based code as if it were synchronous, but without blocking the main thread. So they are simply syntactic sugar for creating functions that return and wait for Promises. Async functions work like this:

A) Fulfilling the Promise of an async function:

async function asyncFunc() {
    return 'result';
}

which is equivalent to:

function asyncFunc() {
    return Promise.resolve('result');
}

which is same to:

function asyncFunc() {
    return new Promise((resolve, reject) => {
        return resolve('result');
    });
}

B) Rejecting the Promise of an async function:

async function asyncFunc() {
    throw new Error('We have error!');
}

which is equivalent to:

async function asyncFunc() {
    return Promise.reject(new Error('We have error!'));
}

which is same to:

async function asyncFunc() {
    return new Promise((resolve, reject) => {
        return reject(new Error('We have error!'));
    });
}

await operator

The await keyword is used to handle Promises inside the async function. So, handling results and errors of asynchronous computations takes place via await. The operator await (which is only allowed inside async functions) waits for its operand, a Promise, to be settled. It "pauses" the function until asyncFunc is done(fulfilled/rejected), and returns the result(result/error):

  • If the Promise is fulfilled, the result of await is the fulfillment value.

  • If the Promise is rejected, await throws the rejection value.

Promise is fulfilled:

async function asyncFunc() {
    const result = await otherAsyncFunc();
    console.log(result);
}

which is equivalent to:

function asyncFunc() {
    return otherAsyncFunc()
    .then(result => {
        console.log(result);
    });
}

Promise is rejected:

async function asyncFunc() {
    try {
        await otherAsyncFunc();
    } catch (err) {
        console.error(err);
    }
}

which is equivalent to:

function asyncFunc() {
    return otherAsyncFunc()
        .catch(err => {
            console.error(err);
        });
}

Error Handling

With promises, an async function have two possible return values: resolved value, and rejected value. And we can use .then() for normal case and .catch() for exceptional case. Let's see how we handle errors in async functions:

A) try…catch statement

The most standard way is to use try...catch statement. When await a call, any rejected value will be thrown as an exception. Here is an example:

async function asyncFunc() {
    try {
        await otherAsyncFunc();
    } catch (err) {
        console.error(err);
    }
}

The catched error is exactly the rejected value. After we caught the exception, we have several ways to deal in catch(err) {...} block with it:

  • Handle the exception, and return a normal value (NOT error). (Not using any return statement in the catch block is equivalent to using return undefined; and is a normal value as well.) catch(err) { return 'fail' }

  • Throw it (err), if you want the caller to handle it. catch (err) { throw err }

  • Reject it, like return Promise.reject(error). This is equivalent to throw error. catch (err) { return Promise.reject(err) }

B) Using .catch

As we declare before the functionality of await is to wait for a promise to be fulfilled or rejected. That's why we can handle the await otherAsyncFunc as a Promise using then or catch method (as an async function always returns a Promise). So we can write error handling like this:

function asyncFunc() {
    const result = await otherAsyncFunc()
        .catch((error) => { console.log(error); });
}

Of course after we caught the exception in .catch method we can use the above way to deal it.

How it works

  • There are Async Functions. These are declared by prepending the word async in their declaration: async function asyncFunc() {....}

  • An Async function always returns Promises.

  • Your code can be "paused" waiting for an Async Function with await.

  • await returns whatever the async function returns when it is done. It will return result if Promise is fulfilled or will throw an error if Promise is rejected.

  • await can only be used inside an async function. If you try to use await operator outside of an async function you will get Error.

  • If an Async Function throws an exception, the exception will bubble up to the parent functions just like in normal Javascript, and can be caught with try/catch or we can add .catch() method directly in await asyncFunc.catch(error => { }) just like in Promises.

Conclusions:

  • An Async function always returns Promises, whether you use await or not (if no await is present the execution is not paused and your code will then be executed non-blocking manner, the promise starts its execution when we invoke it). They are simply syntactic sugar for creating functions that return and wait for Promises. The async keyword just declares that the asyncFunc() function returns value which is guaranteed to be a promise, so that callers can call asyncFunc().then(...) or await asyncFunc() safely. So when we use async keyword we create an asynchronous functions that always return a Promise.

  • We can handle an Async function when we call it, exactly like Promise.

  • await operator "pauses" an Async Function.

  • await returns whatever the async function returns when it is done. It will return result if Promise is fulfilled or will throw an error if Promise is rejected

  • Best approach to handle errors of Async function is using try...catch statement, but of course we can use .catch() method directly in async func when we call it.