DEV Community

Chinmay Mhatre
Chinmay Mhatre

Posted on

Crash course in Asynchronous JavaScript (Part 1)

Introduction

Asynchronous JavaScript can be a daunting concept to learn. However, it is a essential tool in the toolkit of a JavaScript programmer. It can be used to improve the user experience. We'll understand more about the importance of Asynchronous code as we go along further in the article.

Topics that we'll look into :

Part 1

  • JavaScript Call Stack
  • What Does Asynchronous Mean
  • AJAX
  • APIs and WebAPIs
  • CallBacks

Part 2

  • Promises
  • Async and Await
  • Making Http Request
  • API Project

Prerequisites

Basic knowledge of JavaScript is required.

Note

The goal here is to have an understanding about how all the puzzle pieces fit into the bigger picture.

Let us begin by understanding how JavaScript works .

JavaScript call stack

JavaScript is a single threaded language. It means that JavaScript can only run one piece of code at a time. It does so using something called as the Call Stack.

Call stack is how the JavaScript engine keeps track of its place in the script and also manages the different function calls. Stack is a data structure which operates on the LIFO(Last in first out) principle .
stack
Here we can see "3" comes last in the stack so it will be the first one to be executed and after it is executed it will be popped off the stack.
We can visualize this using a tool called loupe

Here is an example :

    console.log("start");
    console.log("End");
Enter fullscreen mode Exit fullscreen mode

flow 1

  • When we run this code the first log goes into the call stack.
  • After execution, it is popped off the call stack
  • Then the second log is pushed into the stack.
  • After execution it is popped off and the program ends

This is what we call synchronous flow (One after the other).
Whenever we search anything on google, we see that the page refreshes and waits for the response. This is the default synchronous behavior. The programs waits for the response.

What does Asynchronous mean

Let us understand Asynchronous with an example :-
image

Whenever we are searching something on the YouTube search bar, we can see suggestions as soon as we start typing .
This basically means that requests are being made to the server behind the scenes to get the suggestion after each letter you type.
This however, doesn't block the UI of the website improving the experience of the user. This is called as an Asynchronous request.

Let us take an example of the setTimeout function :

console.log("start")
setTimeout(function(){
    console.log("middle")
},1000)
console.log("end")
Enter fullscreen mode Exit fullscreen mode

What do you think is the output of this code ?

start
middle 
end
Enter fullscreen mode Exit fullscreen mode

Since JavaScript as we saw is single threaded, the above output should be correct right? But the output is different from what we might expect .

This is the actual output of the script.

start
end
middle
Enter fullscreen mode Exit fullscreen mode

It seems JavaScript moved ahead by printing start and end first, then the setTimeout ran asynchronously, waited for 1sec and returned the result. So why does this work? How can JavaScript hold the variable and continue executing the code simultaneously?

So the thing is the setTimeout is actually not part of javascript. It is what we call a browser API . We will understand more about APIs in the next section but hang with me for a bit.

Web Browser APIs are like super powers provided to us by the browser. For example it can do something like holding a value with setTimeout for a specific amount of time and then returning the value.

working of the setTimeout function

setTimeout

  1. Line one is pushed into the stack and 'start' is printed in the console.
  2. setTimeout is pushed into the stack.
  3. The call stack pops the function then asks the browser API that "Hey Browser ! Hold the value in the function for 1 sec and remind me to run it after the time is up"
  4. The call stack moves ahead with the next line of code and prints 'end' in the console
  5. After the time is completed the browser API then tell the call stack that "Hey remember the function I was holding, you can execute it now".
    loki-Trim

  6. Finally "middle" is printed in the console.

Asynchronous however is not limited to setTimeout function.

why do we need asynchronous code

  • Although some requests may not take much time, some requests like getting data from a database or an API may take a few seconds .
  • If we make these requests synchronously it will block the UI while getting the data, since JavaScript can perform only one task at a time. This will degrade the user experience.

Some things that may need an Asynchronous request include :

  • Getting data from a database.
  • Verify user while login and signup.
  • Getting JSON data from an external Web API.

AJAX

  • AJAX stands for Asynchronous JavaScript and XML.
  • AJAX is not a technology or tool, it is a concept .
  • It is just a terminology used for describing asynchronous code.
  • When we asynchronously exchange data with the server it is called as an AJAX request.
  • We can also update the page without reloading the web page.

So what does the xml part in ajax means?

  • When we talk about exchanging data with different servers running different technology, there has to be a single format of data that can be understood by all the servers .
  • XML and JSON provide us these interfaces which let us transfer data in a format understood by all.

XML

  • XML stands for eXtensible Markup Language .
  • It is similar to html in the sense that it also uses tags like HTML.
  • However the key difference is that, HTML is used for displaying data and XML is used for storing and transferring the data.

SYNTAX

<note>
  <date>2015-09-01</date>
  <hour>08:30</hour>
  <to>Tove</to>
  <from>Jani</from>
  <body>This is a reminder</body>
</note>
Enter fullscreen mode Exit fullscreen mode

JSON

JSON stands for JavaScript Object Notation. It also is a format for transferring data. It is an alternative to xml. JSON is really easy to read and understand. Even though it looks like JavaScript objects JSON can be used independent of JavaScript to transfer data . Many programming languages have ability to parse and read JSON.

The two primary parts that make up JSON are keys and values. Together they make a key/value pair.

  • Key : A key is always a string enclosed in quotation marks.
  • Value : A value can be a string, number, Boolean expression, array, or object.

JSON is a more popular format than XML.

Anyone who is familiar with JavaScript objects will understand JSON very easily.
modern APIs mostly use JSON to transfer and store data.

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
    }   
  ]
}
Enter fullscreen mode Exit fullscreen mode

What is an API?

API is the acronym for Application Programming Interface.
API is an interface which has a set of functions that allow programmers to access specific features or data of an application, operating system or other services.

Web APIs

Often when we talk about APIs in terms of web development the APIs refer to 'Web APIs'.

Web API as the name suggests, is an API over the web which can be accessed using HTTP protocol.

Typically when we make a request to a webpage we get all sorts of data like html, CSS, JavaScript. On the contrary when we make asynchronous request through JavaScript we might want a particular part of the data.

Web API takes requests from the different type of client devices like mobile, laptop, etc. and sends them to the web-server to process it and returns the desired data to the client.

For example: Twitter's APIs provide access to read and write data using which we can integrate twitter's capabilities into our own application. We could for instance, get data about the users tweets and use it in our own application.

api

The data given by the API can be anything for example : images, JSON objects etc.

  • We'll understand these APIs HTTP requests in detail a little later but stick with me for a while .
  • API requests are like any other HTTP request you make to different websites in the search bar like google, Facebook etc. but response from the API is without the unwanted data (html, css etc.).

Let's take an example to understand this better

This is a Pokémon API .It returns an image of a Pokémon when we send it a request. we have to replace the id with the id of the Pokémon we want . 1 is Bulbasaur etc.
image
This is what we get when we send a request to https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png .

You all can also give it a try! Just put the above link in the browser and you'll get back the image. You can also try changing the id to see what different results you get.
It is just like any other http request but only with the data(image).

Query Strings

In the URL of the API we had to replace the id of the image according to what we want.
That is basically a query string. It request the data according to the value we pass in the query string .

Let take another example

This is another API that we will be using later.

In the url, ?q=:query is called as the query string and :query is a variable. The response changes according to the value of the query variable.

With the Pokémon API, we took a simple example which returns the data instantaneously. However, some actions like retrieval of information from a database may take some more time or might even get rejected. Thus we have to take into consideration handling the errors that we might get.

We will discuss the various ways to make async request in a few sections.
But before that we'll have to see how to handle the failure of the asynchronous request.

Callback function

Definition

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

Whatttttt!!!!

neville

Here is an example :

const success = ()=>(
console.log("success")
)

const fail = ()=>(
console.log("fail")
)

const check = (success,fail)=>{
const a = 2 
if(a == 2){
 success()
}else{
 fail()
}}

check(success,fail)
Enter fullscreen mode Exit fullscreen mode
  • Let us assume there are 2 functions success and fail
  • We pass these two function as arguments to a third function called check.
  • When check is executed it calls the success function if the variable 'a' is equal to 2 else it calls the fail function.
  • The success and fail function are called as callback functions since they are passed as arguments and invoked within a check function after something happens.

Alright! Let's bring out our friendly neighborhood setTimeout function again.

  • As we know there are 2 parameters to the setTimeout function . First is a function and second is a delay .
setTimeout(someFunction,delay)
Enter fullscreen mode Exit fullscreen mode

Let us make a function and pass it to setTimeout

const message = function() {  
    console.log("I Have been waiting for 3 sec !!!");
}
setTimeout(message,3000)
Enter fullscreen mode Exit fullscreen mode

The setTimeout which is like an outer function calls the "message" function which is an argument. Here, message function is a callback function.

  • Let us see how the setTimeout is defined.
setTimeout(message,3000){
/*
some code which will hold the value for 3 secs 
*/
message()
}
Enter fullscreen mode Exit fullscreen mode
  • We see that the function(message) which was passed to setTimeout as an argument was called within setTimeout.

Passing callbacks may not be the best way

  • Suppose we want to write a script in which we have to execute multiple async operations but only after the previous operation completes . In this scenario callbacks may not be our best option. Let us see why.

  • Let's say we are writing a function to change the background colour of the body to the different colors of the rainbow. However, each colour should appear 1 sec apart from each other. For example red appears after 1 sec, orange appears after 2, yellow appears after 3 and so on.

rainbow

  • We understand that we can use the setTimeout to delay the colours. However, we cannot just use them independent of each other, since we will have to calculate the delay.
/* assume that red , orange , yellow are
 the functions to change the bg color to the respective colour.*/
setTimeout(red,1000);
setTimeout(orange,2000);
setTimeout(yellow,3000);
Enter fullscreen mode Exit fullscreen mode
  • We could pass a callback to a function which basically runs the next setTimeout only after the previous setTimeout finishes.
  • It'll look something like this :
const delayedColorChange = (newColor, delay, doNext) => {
    setTimeout(() => {
        document.body.style.backgroundColor = newColor;
        doNext();
    }, delay)
}
Enter fullscreen mode Exit fullscreen mode
  • So, how will we go about calling this function?
  • let's say we want to change the colour to red then to orange.
  • The "doNext" argument will contain a callback that again calls the delayedColorChange function but now with the colour as orange. something like this
delayedColorChanged("red",1000,()={
  delayedColorChanged("orange",1000,()=>{
   //This function will be empty since we want to end the 
//color change 
    });
})
Enter fullscreen mode Exit fullscreen mode
  • Now lets say we want to change the colour to yellow after orange.
delayedColorChanged("red",1000,()={
  delayedColorChanged("orange",1000,()=>{
    delayedColorChanged("yellow",1000,()=>{
      //This function will be empty since we want to end the 
      //color change 
    });
  });
})
Enter fullscreen mode Exit fullscreen mode
  • Let's now make a full rainbow.
delayedColorChange('red', 1000, () => {
    delayedColorChange('orange', 1000, () => {
        delayedColorChange('yellow', 1000, () => {
            delayedColorChange('green', 1000, () => {
                delayedColorChange('blue', 1000, () => {
                    delayedColorChange('indigo', 1000, () => {
                        delayedColorChange('violet', 1000, () => {
                             //This function will be empty since 
                             //we want to end the 
                            //color change
                        })
                    })
                })
            })
        })
    })
});

Enter fullscreen mode Exit fullscreen mode
  • It gets a little confusing as we go on nesting more callbacks.
  • Even though we just used one callback function here it got pretty crazy. APIs or any kind of async request will have two of them, success and failure. In that case, there will be a lot of nesting .

nesting

  • Let us assume fakeRequestCallback(url,success,failure) is a fake function that will request the URL for data.
  • success and failure are two callback functions.
  • If no error, success is called, else the failure is called.
  • Here is what happens when we make requests to multiple pages but only after the previous request is successful, similar to the rainbow function.
fakeRequestCallback('books.com/page1',
    function (response) {
        console.log(response)
        fakeRequestCallback('books.com/page2',
            function (response) {
                console.log(response)
                fakeRequestCallback('books.com/page3',
                    function (response) {
                        console.log(response)
                    },
                    function (err) {
                        console.log("ERROR (3rd req)!!!", err)
                    })
            },
            function (err) {
                console.log("ERROR (2nd req)!!!", err)
            })
    }, function (err) {
        console.log("ERROR!!!", err)
    })
Enter fullscreen mode Exit fullscreen mode

sigh

Welcome to callback hell .

If there are multiple async operations to be performed and we try to use our good-old callbacks , we’ll find ourselves in the callback hell .

Let us see if there is a better way in part 2.

Top comments (4)

Collapse
 
ravi_sh_ing profile image
K Ravi Shankar

It's like you've lived with JS your entire life. Splendid work man !!
Loved those gifs,real time examples ... everything in fact.

Collapse
 
chinmaymhatre profile image
Chinmay Mhatre

Thank you !!😄

Collapse
 
retumishra22 profile image
Retumishra22

Very informative!
Explained everything in very simple manner so that anyone can understand it. Keep posting more advanced articles. Thanks a lot for sharing.
Waiting for the Part 2 !!

Collapse
 
ashwith25 profile image
Ashwith Poojary

Very well explained 🔥