My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Asynchronous JavaScript

Asynchronous JavaScript

Rishabh Kumar Bothra's photo
Rishabh Kumar Bothra
·Sep 20, 2021·

6 min read

Javascript code runs on a single thread and hence should be synchronous in nature. Synchronous code waits for one action to complete before moving on to the next task. But even though JS is considered as single-threaded we are able to perform tasks parallelly HOW?

var test = readSync(file_loc);
        console.log(test);
        var test2 = readSync(file_loc2);
        console.log(test2);

This task is done synchronously as the first file is fetched and the test is logged then the next file is fetched and logged. What if the file1 is a huge file and lets say
take 10sec to be fetched then this becomes blocking i/o and decreases UX.
So to get rid of this situation we can perform the same task asynchronously

readAsync(file_loc,(test)=>{
            console.log(test);    
            });

            readAsync(file_loc2,(test2)=>{
            console.log(test2);    
            });

In this case, file1 and file2 both are fetched parallelly and the file which is fetched first is being logged first this becomes non-blocking code and takes lesser time to execute.

first.png

What is Asynchronous JavaScript?

Asynchronous JS basically means codes that start now, and finishes at a later point in time, and can perform any other task simultaneously in the time.

Fetching data from a JSON file using AJAX request:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax</title>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script>
        window.onload = function() {

            $.get("zap.json", function (data) {
                console.log(data);
            });

            console.log("later");
        };
    </script>
</head>
<body>

</body>
</html>

output

second.png

Here later is printed first while the data is being fetched from JSON file and as soon as the data is fetched then the callback function is fired and data is being printed.

AJAX : Asynchronous JavaScript And XML
Communicate with the server by making an HTTP request and retrieves data from the server without reloading the page which we can further use that data in our code. XML refers to as the data which we try to fetch, we can also use JSON instead of XML. Consider google maps as an example, we are able to fetch different locations without refreshing the page, that's how AJAX is advantageous.

How AsyncJS works?

  • Callback
  • Promises
  • Generators

Callback function

A callback function, also known as a higher-order function, is a function that is passed to another function as a parameter, and the callback function is called inside the otherFunction. A callback function is essentially a pattern, and therefore, the use of a callback function is also known as a callback pattern.
Callback implemented using jQuery

window.onload = function() {

    $.ajax({
        type:"GET",
        url:"zap.json",
        success:function(data){
            console.log(data);

            $.ajax({
                type:"GET",
                url:"test.json",
                success:function(data){
                    console.log(data);

                    $.ajax({
                        type:"GET",
                        url:"test2.json",
                        success:function(data){
                            console.log(data);
                        },
                        error:function (err) {
                            console.log(err);
                        }
                    })


                },
                error:function (err) {
                    console.log(err);
                }
            })


        },
        error:function (err) {
            console.log(err);
        }
    })
};

Here function inside a function is being called only if the previous function executes without any error this is called callback functions. See the pyramid shape and all the }) at the end? Eek! This is affectionately known as callback hell. :fearful:

Output third.png

Callback hell can be resolved by Modularizing our code and handling every single error. The above code be rewritten by resolving callback hell as:

window.onload = function() {

    function checkerror(err) {
        console.log(err);
    }

    $.ajax({
        type:"GET",
        url:"zap.json",
        success:friends,
        error:checkerror
    });

    function friends(data) {
        console.log(data);

        $.ajax({
            type: "GET",
            url: "test.json",
            success: test,
            error: checkerror
        });

    }

        function test(data) {
            console.log(data);

            $.ajax({
                type: "GET",
                url: "test2.json",
                success: function (data) {
                    console.log(data);
                },
                error: checkerror
            })


        }
};

Here errors are handled as different functions and every callback function is declared outside which keeps the code tidy and readable. Output remains the same :relieved:

Promises

Promise is an object which shows a particular task has been completed or not(i.e. state of a particular task).

A promise may be in one of 3 possible states:

  • Fulfilled: the operation was completed successfully.
  • Rejected: the operation failed.
  • Pending: initial state, neither fulfilled nor rejected.

Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.

The promise is better than a simple call back as we can directly use a return statement and pass new promises directly, it makes code more readable and understandable, and easy to execute.

fourth.png

Let us consider an example to understand better that how it is better than normal callbacks.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Promises</title>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script>
        window.onload = function(){

            $.get("zap.json").then(function (value) {
                console.log(value);
                return  $.get("test.json");
            }).then(function (value) {
                console.log(value);
                return  $.get("test2.json")
            }).then(function (value) {
                console.log(value);

            })
        }
    </script>
</head>
<body>

</body>
</html>

output remains the same
third.png

function in .then is called when the data is retrieved and we can return new promise, hence it makes our code readable and output remains the same.

fifth.jpeg

Generators

Generators provide a powerful alternative: they allow you to define an iterative algorithm by writing a single function which can maintain its own state.

sixth.png

generators are a special type of function which is used to perform async tasks. It is defined as function*(){..} on calling similarly as functions it returns an iterator. In JavaScript, an iterator is an object that provides a next() method that returns the next item in the sequence.
Let us consider an example :

window.onload = function () {

   generator(function*(){
        var zap = yield $.get("zap.json");
        console.log(zap);
   });

    console.log("done");

    function generator(temp) {

        var gen = temp();

        function checkandprint(output){
            if(!output.done) {
                output.value.then(function (data) {
                    return checkandprint(gen.next(data));
                });
            }
        }

            return checkandprint(gen.next());
    }
};

here next() returns the value of done as true or false and the iterator is terminated when done is false.
The next() method also accepts a value that can be used to modify the internal state of the generator. A value passed to next() will be treated as the result of the last yield expression that paused the generator. This pause helps us make user-defined iterables.

seven.png

There is no opposition between these two techniques. They exist together complementing each other nicely. Promises resolve the callback hell problem but even in promises there are callbacks and if the code is huge it becomes difficult to debug an issue. So we want to write asynchronous code in synchronous manner, Here comes the generators which gives us the power to write asynchronous code which seems to be synchronous using promises, this combined concept is called Async/Await

What is the best way among all?

eight.png

Now, this totally depends on the use case. Different methods have different advantages and disadvantages.
Callbacks are the fastest solution possible at this time (performance of native promises are not soo good). Promises with generators give you the opportunity to write asynchronous code in a synchronous fashion. But for now, they are much slower than simple callbacks.

Further Readings

Promises

Callbacks

Generators