Skip to main content

Command Palette

Search for a command to run...

Event Loop in Javascript

Updated
•3 min read•View as Markdown

To understand event loop better, let us start with the definition of javascript. Javascript is a single threaded, asynchronous, non-blocking, client-side scripting language.

Javascript is a single-threaded language, meaning it has only one call stack and can execute only one task at a time. The environment provides external APIs to handle operations like timers, network requests etc. which are time consuming without blocking the main thread. The event loop continuously monitors the call stack and the callback queues. When the call stack becomes empty, the event loop moves the queued callbacks into the stack for execution. This mechanism makes Javascript non-blocking and asynchronous even when Javascript is single threaded.

CALLSTACK:

Javascript engine uses a data structure known as call stack, where all the code is executed. It follows the LIFO principle, last-in, first-out which means the function added in the end will be executed the first. Call stack quickly/immediately executes the code put in it.

When a function is called, an execution context is invoked, it is the environment where the code is evaluated and executed. It has all the necessary information related to the currently running code like the functions, variables, etc.

Push operation, when a function is called, its execution context is pushed onto the top of the stack and when a function finishes executing, its context is popped of the top of the stack.

Whenever any JS program is run, a general execution context is the first item pushed into the stack forming the base. There can be only one GEC at a time since Javascript is single-threaded. Every GEC is created in 2 phases: a memory creation phase where Javascript engine scans the code and allocates the memory to variables and functions before the code is executed. Then there is the code execution phase where the code is executed line by line where actual values to variables and functions is given as they are encountered. When the code is done, GEC also pops out of the call stack.

A common question that arises here that, what happens when the call stack is busy?

When the call stack is busy, the JS engine cannot run any other code and the application can become unresponsive. To avoid such issues, long functions should be broken up or moved to a separated background thread.

WEB APIs:

In the JS runtime environment, Web APIs such as console. location, setTimeout, DOM APIs, fetch(), etc. handle asynchronous operations outside the main thread. Simultaneously running the time taking operations and gives result when ready, this way the main thread is not blocked and the application stays responsive.

When the function is pushed onto the call stack and passed to the relevant web api to be handled in the background, the function is popped off the call stack so that the synchronous code can still run smoothly.

CALLBACK QUEUE:

Now the Web API has finished its job but the associated callback function is not executed immediately, it is placed in the callback queue and waits to get executed. It follows the FIFO principle, meaning first-in, first-out. The event loop monitors the whole process and puts the function from callback queue into call stack once the call stack is empty. The event loop prioritises microtask queue over the callback queue, once the microtask queue (holds callbacks for promises and mutation observer tasks) is over then only the callback queue(holds callbacks for setTimeout, setInterval, etc) is executed in the call stack.