In this article we will try to figure out how event loop and concurrency actually works in javascript.

Javascript, a single-threaded functional language.

One thread == One call stack == One thing at a time

Have you ever wondered that despite of being single-threaded functional language, how javascript handles our callback? During execution, where does our callbacks go and how they come back in our call stack after certain amount of time? So, lets try to figure out how javascript executes the functions internally.

We will start with a simple function execution. Let’s assume we have the following code snippet, so when we execute it, internally javascript engine creates three main components during run time.

function a(){
 console.log(“a”);
 b();
}
function b(){
 console.log(“b”);
}
a();

Call Stack — It is the main thread by which execution of our program takes place. During run time, engine creates frames, which contains arguments and variables of that function (not objects) and push them into call stack. main is our entry frame by which execution starts, after that it will create a frame for a and push it into call stack. Inside a we are calling b, so it will create a frame for b and push it into call stack. When execution of any function finishes, it will pop corresponding frame from the call stack.

Object Heap — It is nothing but a memory space where objects resides.

Message Queue — During execution, javascript engine (V8) also maintains a message queue. Whenever the browser finds out that timer for a particular callback is completed it pushes that function to the message queue. It is a pipe which browser uses for sending their event to the main execution call stack for execution. So message queue is nothing but collection of callbacks those are waiting for the execution.

Now, for some more clarity, let’s extend our example and add some callbacks. We will use ‘web api setTimeout’ to add function aa and bb inside function a and b respectively with timeout 3000ms and 100ms.

setTimeout is a web API which is handled by the browser concurrently. You can call web API’s and they will keep working on them in separate thread.

function a() {
console.log(“a”);
setTimeout(function aa() {
console.log(“aa”);
}, 3000);
b();
}

function b() {
setTimeout(function bb() {
console.log(“bb”);
},100);
console.log(“b”);
}

a();

Starting with main frame, engine will create frame for function a and push it to call stack and browser start timer for function aa. After that, engine creates frame for function b and pushed it into call stack. Similar as aa, for function bb also, browser kicks a timer for it.

On the one hand, the call stack execution is going on and it pops frames from call stack as ba and then main, and on the other hand at the same time callback timer is ticking. Whichever callback timer completes its duration first (regardless which started first), it will move to the message queue. So, in this case, even though timer for aa started first it is taking more time then bb so in message queue, bb moves before the aa.

Now significance of Event Loop comes in picture.

Event loop is continuously ticking during the whole process and watching the call stack and message queue. As soon as it finds out that all frames of call stack (a, b and main) are popped and call stack is empty, it started creating frames for callback functions (bb, aa) and pushing them into call stack from message queue. Here you can see event loop waited for the completion of previous call stack before pushing message queue frames to them. It means whatever time we provide in the callback, that is the minimum time which it will take to execute.

Conclusion

So the crux is, even though Javascript is single-threaded, our browser and node provides us the API’s which we can call for concurrency execution and event loop will help in pipelining those execution results from message queue to the call stack.

Author