JavaScript Event loop
JavaScript is a single-threaded programming language. Single-threaded means it can do one thing at a time.
In Synchronous operation code will be executed line by line
In Asynchronous operation means that a process operates independently of other processes.
Example: if we use SetTimeout() function, a web API given by browser. which make sure that our code is executes after specified time
Now let’s see the Basic Architecture:
Fig1.Event Loop
Heap: This is where all memory allocation happens for your Variable.
Call Stack (LIFO): It present at JavaScript engine all the code of JavaScript in executed inside this call Stack.
Web API: This is where our asynchronous code gets processed.
Callback Queue (FIFO): This is where our asynchronous code gets pushed to and wait for the execution.
Event loop: it continuously watch the call stack to check whether it is empty as soon as it found. empty call stack, it pulled call back from queue & pushed to call stack for execution. Hence, functions added to it are processed in a first-in-first-out order.
Let’s understand this with a code example:
console.log(“Start”);
setTimeout(function() {
console.log(“callback”)
},5000);
console.log(“End”)
Output:
Start
End
callback
Explanation:
console.log(“Start”);
When the first line executes it’s a console.log(). This is a function invocation which means that this function is pushed into the call stack where it executes printing ‘Start to the console. Finally, it’s returned and is popped off the stack.
setTimeout(function() {
console.log(“callback”)
},5000);
Then when the runtime goes to execute setTimeout() it knows that this is a web API. Therefore, it gives it off to the browser to handle its execution. The browser starts the timer and then JS runtime pops the setTimeout() out of the stack. It encounters another console.log() invocation and so it pushes this into the call stack, the message ‘End’ is logged into the console, and then it’s finally returned. Then the last console.log() is popped off the stack. Now the call stack is empty.
Meanwhile while all of this was going on the timer finishes. When 5 seconds have elapsed the browser goes ahead and pushes the callback function into the callback queue.
Next the event loop checks if the call stack is free or not. Since it is free it takes the callback function and pushes it again back to the call stack which executes the code inside it.
console.log(“End”)
Again, inside the code there is a console.log() invocation so this function goes to the top of the stack executes which logs ‘callback’ into the console and finally it returns. This means it gets popped off the stack and finally the callback gets popped off the stack and we are done.
ES6 Job Queue/ Micro-Task queue:
Fig2.Event Loop
ES6 introduced the concept of job queue/micro-task queue which is used by Promises in JavaScript. Macrotask or just called the task queue is code which needs to be executed after execution stack is empty. Macrotask are non blocking in nature. setInterval, setImmediate, setTimeout, I/O tasks, DOM Manipulation use the macrotask queue to run their callbacks. Promises, MutationObservers, IntersectionObservers etc. use the microtask queue to run their callbacks.
The difference between the message queue and the microtask queue is that the microtask queue has a higher priority than the message queue, which means that promise jobs inside the job queue/ micro-task queue will be executed before the callbacks inside the message queue.
Let’s summarize what we have learned.
JS is single threaded but able to perform asynchronously by sending out certain functions to the browser utilizing built in Web API’s. With a message queue available in our event loop we are able to build our applications around a collection of asynchronous callback functions. Thus freeing the runtime to handle our current operations while we wait for the external events to happen.