DEV Community

loading...
Cover image for Hard Parts of Asynchronous Javascript

Hard Parts of Asynchronous Javascript

tashfeenrao profile image Tashfeen Rao ・4 min read

Javascript engine runs code line by line which we call synchronous behavior, there's another type of execution that javascript engine does is known as asynchronous javascript. Before jumping into the beautiful world of asynchronous we must understand why we require this type of execution.

when you write code sometimes there is a function whose input depends on another function's output. but if other function takes time to give you the result then what will you do in meantime except waiting which is a very bad practice. In the case of the web when we call API for data it usually takes time to return it is a very frustrating experience for the user if he had to wait until the response comes and do other stuff that can be done in meantime.

A real example for this in your Pc you can open multiple programs and your system don't mind because it has multiple processors it shifts load among them and how is it done? well, you can imagine, it is asynchronous which allows us to run the program in the background.

For understanding the asynchronously javascript. we need to make a mental model in our head to understand what's going on behind the scenes and how the javascript engine executes our code.

In ES6 async functions were introduced for this purpose. let's start with a very basic async function example for making our mental model.

async function createFlow(){
console.log('Me first')
const data = await fetch('https://twitter.com/tashfeen/tweets/1');
console.log(data);
}
createFlow();
console.log('Me second');

Do you have any idea what will be print on the screen? well, let's figure out the answer. First, we want to visualize how this code will execute on the javascript engine.
Javascript engine consists of three main elements
1 Execution context
2 Memory
3 call-stack
The execution context runs the code and displays it on screen. Memory stores variables functions etc. call-stack runs functions in first in last out principle. At the bottom, there is another type call queue-stack that holds those functions that wait for some browser work to finish.

Alt Text

Now you get your visualization. let's see how it gonna be executed our code.

async function createFlow(){
console.log('Me first')
const data = await fetch('https://twitter.com/tashfeen/tweets/1');
console.log(data);
}

At the first line of code, we have a function expression. It will store function definition at Memory and goes to the next line.

Alt Text

Next line is invoking createFlow() function.

createFlow();

Javascript engine first looks into the global Memory is there any function with the name of creatFlow()? yes, it found one then it will put this function inside call-stack and It will create its own execution inside of the global Execution context. Now it start executing function's code line by line.

console.log('Me first');

this will be print on the screen. then it goes to the second line which's a variable definition.

const data = await fetch('https://twitter.com/tashfeen/tweets/1');

It will store the data variable in Memory. Its value is blank in Memory right now. The right side of this variable invokes browser's facade function fetch() which triggers web browser feature work to get the data from the twitter server. fetch() will return promise object which has two things value and onfulfillment[]. When the response comes from the server it fills the value. If there is some work to be done on this value it will be done onfulfillment[]. For visualizing this process, I made a diagram.

Alt Text

Browser background work takes time to get back with data. How we will console.log(data) when we don't have data? Are we going to sit idle and wait for a response? You are right, the answer is NO. But how we execute the rest of the code. Well In the above code you saw special browser feature await which will through us out of function's execution context, and put creatFlow function in queue-stack. Now it came to global execution context and execute next line in code

console.log('Me second');

It'll print Me second on screen. Now there's no other code left for execution.

I am glad that you asked what happened to our

console.log(data)

How will we go back inside of the createFlow() execution context?. Well, when we get a response from the twitter server It'll fill the value property of promise object and put createFlow() on call-stack and start executing where it left earlier. which is
We got our data from the twitter server. which is a string with simple HI It fills value property of promise object and stores this value = 'HI' in Memory of function's execution context.Now Javascript reads

console.log(data)

Javascript looks for data variable into the Memory and found with data = 'HI' Which will be print out on screen after about 200ms.

Alt Text

This is asynchronous we left some code for running in background which requires some time to finish. We get back to other code and start executing it. When we got our response we execute left code. Now the execution cycle is complete.

Discussion (0)

pic
Editor guide