Asynchronous nature of Javascript

  • Key points on how Javascript code work?

    • Whenever a javascript function gets called it goes into call stack and depending on what kind of function it is, it gets processed further.

    • The concept that call stack follows is Last In First Out (LIFO), so every call gets added in the stack and it gets executed, if it is synchronous then we will get the call executed immediately then the function will be popped out from the stack after execution.

    • Those function who are asynchronous in nature, gets stored in event queue of their respective environment.

    • While this goes on, our event loop keeps on looking inside the call stack that whether it is empty or not. If it is empty then It puts the function from event queue in call stack, it doesn't care whether the function that it will put in call stack is completely executed or not in the event queue. Now there are multiple asynchronous call handling API's like node js runtime environment, web API's provided by browsers, etc.

    • Their they get executed and then popped out from call stack.

An illustration of call stack

What are the ways to make code asynchronous?

  • So, whenever we use any fetch API's in our js functions or any node module like fs, etc or when we use any timer functions like setTimeout, setInterval, closeInterval, etc. There are few functions in these API environment that are asynchronous like fs.readFile, fs.writeFile, etc.

  • So, whenever we call these functions our code becomes asynchronous and needs to be handled with caution, if we are not aware of their nature then we might fail in our code.

setTimeout(() => {
    console.log("Printing only after 1 second")
}, 1000)

let users = fetch('https://jsonplaceholder.typicode.com/users').then((data)=> 
{
    data.json()
}).then(data => {
    return data
})

What is event loop?

  • Event loop is a property of javascript's runtime time environment. Event loop is responsible for execution of asynchronous call in javascript as it continuously checks the call stack whether it is empty or not. Any function that is asynchronous get stored in event queue and then with the use of event loops it gets executed on call stack.

  • Event loop is a property of javascript's runtime time environment. Event loop is responsible for execution of asynchronous call in javascript as it continuously checks the call stack whether it is empty or not. Any function that is asynchronous get stored in event queue and then with the use of event loops it gets executed on call stack.

console.log('Start');

// Asynchronous operation (simulated using setTimeout)
setTimeout(() => {
    console.log('Async operation 1');
}, 2000);

// Synchronous operation
console.log('Sync operation');

// Another asynchronous operation
setTimeout(() => {
    console.log('Async operation 2');
}, 1000);

console.log('End');

Here, We have two setTimeout asynchronus functions, which will go through the Web API's provided by browser, then into the callback/event queue, then depending upon call stack's availability then will get executed in this order.

Start
Sync operation
End
Async operation 2
Async operation 1

Since, synchronous code gets executed directly from call stack, so that's why they are printed first and then the setTimeout.

What is callback?

  • Callbacks are function that are passed to another function as an argument. These functions become very handy while dealing with asynchronous functions. There is a error first callback function, mainly used for that. It helps us to change the nature of asynchronous function in a way, callback function gives us some outcome on execution whether it has an error or any data. Then while executing that callback function we only proceed further if we don't have any error. So, In this way we ensure that we we only reach to the next step, if we have correct output.
function print_data(url){
    fetch_data(url, (err, data) => {
        if(err){
            console.error(err)
        } else{
            console.log(data)
        }
    })
}

function fetch_data(url, callback ){
    fetch(url).
        then((data)=> {
            return data.json()
        }).then(data => {
            callback(null, data)
        }).catch((err) => {
            callback(err, null)
        });
}
print_data('https://jsonplaceholder.typicode.com/users')

Here, I do a fetch request and with the help of callback, I ensure that I only print the data fetched once the fetch request is completed. So, It plays a very Important role in managing asynchronous functions.

What are the web Browser API's?

  • Web browser API's provide us multiple methods to interact with the DOM (Document Object Model) of our web page. It also provides up event listeners like onclick, keydown, etc that makes our web page interactive.

  • Any DOM manipulation using 'Document' interface is provided by the web browser API's

  • Also provides us multiple tools like "fetch" and time based functions like setTimeout and setInterval, etc.

  • It also gives up features like localStorage for storing the client side data locally.