What is the Event Loop?
At its core, the JavaScript event loop is responsible for managing the execution of code, collecting and processing events, and executing queued tasks. JavaScript operates in a single-threaded environment, meaning only one piece of code runs at a time. The event loop ensures that tasks are executed in the correct order, enabling asynchronous programming.
Call stack
Call stack keeps track of the functions being executed in a program. When a function is called, it is added to the top of the call stack. When the function completes, it is removed from the call stack. This allows the program to keep track of where it is in the execution of a function and return to the correct location when the function completes. As the name suggests it is a Stack data structure which follows last-in-first-out.
Web APIs/Node.js APIs
Asynchronous operations like setTimeout(), HTTP requests, file I/O, etc., are handled by Web APIs (in the browser) or C++ APIs (in Node.js). These APIs are not part of the JavaScript engine and run on separate threads, allowing them to execute concurrently without blocking the call stack.
Task queue / Macrotask queue / Callback queue
The task queue, also known as the macrotask queue / callback queue / event queue, is a queue that holds tasks that need to be executed. These tasks are typically asynchronous operations, such as callbacks passed to web APIs (setTimeout(), setInterval(), HTTP requests, etc.), and user interface event handlers like clicks, scrolls, etc.
Microtasks queue
Microtasks are tasks that have a higher priority than macrotasks and are executed immediately after the currently executing script is completed and before the next macrotask is executed. Microtasks are usually used for more immediate, lightweight operations that should be executed as soon as possible after the current operation completes. There is a dedicated microtask queue for microtasks. Microtasks include promises callbacks (then(), catch(), and finally()), await statements, queueMicrotask(), and MutationObserver callbacks.
Example of the Event Loop in Action
console.log("Start");
setTimeout(() => {
console.log("Timeout Callback");
}, 0);
Promise.resolve().then(() => {
console.log("Promise Resolved");
});
console.log("End");
Output:
Start
End
Promise Resolved
Timeout Callback
Explanation:
console.log("Start") executes first.
setTimeout is encountered, and its callback is delegated to the Web API (it won’t execute immediately).
A resolved promise is pushed to the Microtask Queue.
console.log("End") executes.Since the Call Stack is empty, the Event Loop processes the Microtask Queue first, executing Promise Resolved.
Finally, the callback from setTimeout is executed from the Callback Queue.
Summary
The event loop is a core mechanism in JavaScript that allows the single-threaded language to handle asynchronous tasks without blocking the main thread. It works in conjunction with the call stack, which processes synchronous code, and the event queue, where asynchronous tasks wait to be executed. As JavaScript runs, the event loop continuously monitors the call stack, only processing tasks from the event queue when the stack is empty. This system enables efficient handling of I/O operations, user interactions, and background tasks, allowing JavaScript to run smoothly and responsively despite its single-threaded nature.
Top comments (0)