Tags

advanced js
youtube
Web development
vue css
social share buttons
real-life-example
react datetime picker
progra
Online
MathJax
jsfiddle
jquery chart library
instant search using vue
handlebars
event loop
Design
console.log
best practices
Array
yeoman

Show All

Explaining async await of ES8 with examples

author-avatar
Paul Shan Tue Feb 14 2017

A much awaited feature async await is available on your browser now (if you’re using chrome 55 or greater). Firefox will start supporting from version 52 an Safari from 10.1. Others will also follow the path.

So, we can say we have entered the era of async await and now can handle our asynchronous programs with style :)

The journey of asynchronous

When it all started

Since birth JavaScript was asynchronous and we used to handle things with callbacks. So for long operations; it was like, a callback inside another callback, then another one inside that, then another. Used to look like something like below.

function lotOfAsyncWork() {
    request("/api/isLogin", function(response){
        var userId = response.loggedInUserId;
        request("/api/user/detsils/"+userId, function (response2) {
            request("http://github/repos/"+response2.repoName, function (response3) {
                paintTheUI(response3, function () {
                    hideLoader();
                });
            });
        });
    });
}

Promises to the rescue

Due to all those ugly callbacks, an english phrase was being attached to JavaScript. That was “callback hell”. The code used to look really ugly. Then people came up with promises which gave the control back to the callee function to execute any callback. Below is the promise based solution of the above snippet.

function fetchCurrentLogin() {
    return new Promise(function (resolve, reject) {
        request("/api/isLogin", resolve);
    });
}

function fetchUserDetails(response) {
    return new Promise(function (resolve, reject) {
        var userId = response.loggedInUserId;
        request("/api/user/detsils/"+userId, resolve);
    });
}

function fetchGithubDetails(response1) {
    return new Promise(function (resolve, reject) {
        request("/api/isLogin", resolve);
    });
}

function fetchCurrentLogin(response2) {
    return new Promise(function (resolve, reject) {
        request("http://github/repos/"+response2.repoName, resolve);
    });
}

function lotOfAsyncWork() {
    fetchCurrentLogin()
    .then(fetchUserDetails)
    .then(fetchGithubDetails)
    .then(paintTheUI)
    .then(hideLoader);
}

Problem of promise chain

Though the promises have resolved the issue of callback hell till a very good extent. But it also created a problem of promise chaining. Since our code is generally modular and different modules communicate with each other; we started creating a promise chain. And it’s another pain to create and return promises again and again.

promise chain diagram

Introduction to generators

ES6 came up with the concept of generators in which you can do pause and resume kind of operations. Generators can be used in many other corners too; but that pause feature with yield was useful to handle asynchronous in some cases.

Now it’s async await

ES8 came up with async and await keywords which can be used to symbolize a function as asynchronous and to wait or pause till the time it is not resolved. This feature is a mixture of promises and generators.

New async await syntax

The keyword async is used to declare a function as async. The syntax is as simple as putting an keyword async infront of function, which return an AsyncFunction object.


async function myFunc(){
    //function body
}

AsyncFunction object is like a promise. You can use the myFunc().then() function to execute some statements after your async function is completed fully.

Unlike a promise, an async function doesn’t have any resolve or reject callbacks; rather it waits using the await keyword just like the following way.

async function myFunc(){
    var result = await someAsyncFunction();
    return result;
}

You can also use multiple awaits inside a single await function like the following example.

async function myFunc(){
    var result1 = await someAsyncFunction();
    var result2 = await someOtherAsyncFunction();
    return result1 + result2;
}

Once all await are resolved in an async function, it will be considered as completed. The first async function may have a promise or could be using a promise object and the rest will simply await till the previous one is resolved. See the example below of a promise chain.

function baseAsyncFunctionWithPromise(argument) {
    return new Promise((resolve)=>{
        setTimeout(() => resolve(100), 10000)
    });
}

async function secondAsyncFunction() {
    var result = await baseAsyncFunctionWithPromise();
    return ++result;
}

async function finalAsyncFunc() {
    var result = await secondAsyncFunction();
    return ++result;
}

finalAsyncFunc().then((r)=>{
    console.log("finalAsyncFunc resolved with value ", r);
});

The above code snippet will finally print “finalAsyncFunc resolved with value 102”.

Callbacks & async-await

The rule is, you can not use await outside any async function. The immediate parent must be an async and that is the reason why the following code will throw a syntax error.


async function fetchHTML(urls) {
    urls.forEach(url => {
        // syntax error
        const content = await httpGet(url);
        console.log(content);
    });
    console.log("I am tricky");
}
The correct way to do that iteration is as below.

async function fetchHTML(urls) {
    urls.forEach(async url => {
        const content = await httpGet(url);
        console.log(content);
    });
    console.log("I am tricky");
}

However, If you think that "I am tricky" will be printed only after all the async calls are resolved, then you are wrong. Rather "I am tricky" will be printed before any httpGet(url) is resolved. And that is because no one is awaiting for the async callbacks (the await is only there for the httpGet()).

If you want to achieve the synchronous kind of behavior here, you will probably have to go with for of, so that you can avoid the callbacks. Below is the code.


async function fetchHTML(urls) {
    for (const url of urls) {
        const content = await httpGet(url);
        console.log(content);
    }
    console.log("I am tricky. But I will be printed at the end.");
}

Pros of async await

Sync like code

JavaScript is a single threaded language and it just can’t afford to block the thread to wait for an asynchronous function to get resolved. But the handling of asynchronous calls using promise or callback are really a little tough to understand. However async await gave us the power to make a code which looks like and also executes synchronously, but do not block the main thread. This is the reason to introduce async await; thus the biggest pro.

Less silent errors


async function foo() {
    throw new Error('Error!');
}
foo();

The code above would have silently throw an error in previous JavaScript ways, but now in majority of the browsers it's no more silent.

Cons of async await

A con with async await is, it awaits in one after another. Suppose you have a code like below.

async function myAsyncFunc(){
    return await asyncTask1() + await asyncTask2();
}

In this code, JavaScript will run asyncTask1() and will wait till it gets resolved. Then it will trigger asyncTask2() and do the similar thing. So if you don’t have any dependency between asyncTask1 & asyncTask2 and both of them can be triggered parallelly; using two awaits will kind of harm your performance. Though you are open to use Promise.all and await for a single promise returned by that.

JavascriptES7vanilla jsES6ES8

Written By

Paul Shan

Collections

  • E

    ES6

  • R

    React JS

  • C

    CSS

    Cascading style sheets only

  • S

    SEO

    Search engine optimization

  • E

    ES7

  • C

    CMS

    wordpress, drupal, jumla, magento and more


Show All

Tags

advanced js
youtube
Web development
vue css
social share buttons
real-life-example
react datetime picker
progra
Online
MathJax
jsfiddle
jquery chart library
instant search using vue
handlebars
event loop
Design
console.log
best practices
Array
yeoman

Show All

Collections

  • E

    ES6

  • R

    React JS

  • C

    CSS

    Cascading style sheets only

  • S

    SEO

    Search engine optimization

  • E

    ES7

  • C

    CMS

    wordpress, drupal, jumla, magento and more


Show All