Single thread model of JavaScript
All actions in JS are performed on a single thread. However, we can give the appearance of multi-threading by employing a few clever data structures.
The programming language JavaScript is single-threaded. This means that JavaScript can only do one thing at any given time.
A script is executed by the JavaScript engine, starting at the top of the file and working its way down. In the execution phase, it constructs execution contexts and pushes and pops functions onto and off the call stack.
If a function takes a long time to perform, you won't be able to interact with the web browser while it's running since the page will hang. The term "blocking function" refers to a function that takes a long time to perform.
The Event Loop
The runtime model of JavaScript is based on an event loop, which executes the code, collects and processes events, and performs queued sub-tasks. This model differs significantly from models written in other languages such as C programming and Java.
The event loop is a pretty simple concept. There is an eternal cycle in which the JavaScript engine waits for tasks, executes them, and then sleeps while waiting for more.
The engine's overall algorithm is as follows:
Step 1: Execute the duties as soon as possible, starting with the oldest.
Step 2: Sleep till an assignment appears. As soon as the task seems, go to step 1.
Most of the time, the JavaScript engine does nothing; it only executes when a script/handler/event is activated.
How do Event loops work?
The event loop in JavaScript manages the execution of code, handling events, and running tasks.
- Execution Stack: JavaScript runs functions one at a time. When a function starts, it goes on the stack. Once it finishes, it leaves the stack.
- Callback Queue: Some tasks, like user clicks or data fetching, wait in the callback queue. They are ready to run but have to wait until the stack is empty.
- Event Loop Process: The event loop checks if the stack is empty. If it is, the event loop takes the first task from the callback queue and runs it.
- Non-Blocking Operations: JavaScript can continue doing other things while waiting for tasks like fetching data. When these tasks finish, their callbacks go to the callback queue to run when the stack is clear.
- Continuous Cycle: The event loop keeps running in a loop, checking the stack and the callback queue to make sure tasks are done in the right order.
The event loop helps JavaScript run tasks efficiently, allowing the program to stay responsive while handling multiple operations.
Basic Architecture
As previously stated, the JavaScript engine can only perform one task at a time. It's more precise, however, to say that the JavaScript runtime can only accomplish one thing at a time.
Other than the JavaScript engine, the web browser has additional components.
The web browser can do concurrent and asynchronous actions when you use the setTimeout() function, make a fetch request, or click a button.
The web browser's Web APIs include setTimeout(), fetch requests, and DOM events.
The JavaScript engine places the setTimeout() method on the call stack in our example, and the Web API establishes a timer that expires in one second.
Callbacks are functions that can be provided to another function as an argument. After an event has occurred, the callback function can be invoked from the function to which it was provided (caller).
The task() function is then placed in a queue called a callback queue or a task queue by the JavaScript engine:
The event loop is a continuous operation that keeps track of the callback queue and the call stack.
If the call stack isn't empty, the event loop waits until it is, then adds the following function from the callback queue. Nothing will happen if the callback queue is empty:
Example
To understand the working of the event loop, consider the following example:
Approach 1
JavaScript
console.log('Welcome Reader!');
setTimeout(() => {
console.log('Execute it immediately.');
}, 1);
console.log('Bye Reader!');
You can also try this code with Online Javascript Compiler
Run Code
Output
Let's take a glance at another example to see what happens when we run the following code in a browser:
Approach 2
JavaScript
console.log('Start!');
setTimeout(() => {
console.log('Execute it immediately.');
}, 0);
console.log('End!');
You can also try this code with Online Javascript Compiler
Run Code
Because the timeout, in this case, is 0 seconds, the message 'Execute it immediately.' should show before the message 'End!' .That is not the case.
When the call stack is empty, the JavaScript engine places the following function call on the callback queue and runs it. In other words, it is executed by the JavaScript engine after console.log('End!').
Output
You can compile with the help of Online Javascript Compiler for better understanding.
Memory allocation in JavaScript
In JavaScript, memory allocation is handled automatically. When you create variables or objects, JavaScript allocates memory for them without needing manual input from the developer. JavaScript uses garbage collection to manage memory efficiently. This process involves automatically removing data that is no longer in use, which helps prevent memory leaks.
The language’s dynamic typing means that memory is allocated based on the data type at runtime. JavaScript also manages memory through scope, clearing variables from memory when they go out of scope, such as when a function finishes. This automatic memory management allows developers to focus on writing code rather than managing memory directly.
Micro tasks within an Event Loop
A micro-task is a function performed after the operation or programme that produced it has exited and only if the JavaScript execution stack is empty, but before the user agent returns control to the event loop that drives the script's execution environment. A micro-task has the ability to en-queue other micro-tasks.
Micro-tasks are frequently scheduled for tasks that must be accomplished shortly after the current script is completed. The event loop moves on to the micro-task queue after completing one macro-task. The event loop will not move on to the next task outside of the micro-task queue until all of the tasks in the micro-task queue have been finished. This indicates that the micro-task queue is more crucial.
Mutation observer callbacks and promise callbacks are examples of micro-tasks.
Macro tasks within an Event Loop
A macro-task is a separate and independent piece of work. The JavaScript code is always executed here, and the micro-task queue is always empty.
The macro task queue is typically considered the task queue or the event queue.
But the task queue is used for synchronous statements, whereas the macro-task queue is utilised for asynchronous statements.
No code in JavaScript is allowed to run until an event has occurred. It's worth noting that the execution of JavaScript code is a macro-task in and of itself.
Frequently Asked Questions
What is an event in JavaScript?
An event in JavaScript is an action or occurrence, like a user click or page load, that JavaScript can respond to with code.
What is an event loop thread?
An event loop thread manages the execution of code by continuously checking and processing events in the event queue in JavaScript.
What is the main event loop in node js?
The main event loop in Node.js handles asynchronous operations by processing events and callbacks in a non-blocking manner, allowing efficient execution.
What is the event loop and call stack?
The event loop handles asynchronous tasks and callbacks, while the call stack manages the execution of synchronous functions and their order in JavaScript.
What criteria does the event loop use to determine which function to execute next?
There's a queue. When functions are ready to run, they are pushed onto the queue, and the event loop then performs them in order.
Is it guaranteed that if you ask the event loop to run a function at a specific time (as with setTimeout in Javascript), it will?
No, the event loop will do its best, although functionality may sometimes be delayed.
Conclusion
In this article, we have extensively discussed the Single-threaded Model of JavaScript, the Event loop in JavaScript, its Working, and Examples. We also discussed Micro and Macro tasks within the Event Loop.
We hope this blog has helped you enhance your Javascript knowledge of event loops. You can learn more about JavaScript by visiting the free Javascript tutorial by Code360. You can also learn how to create a quiz app using Javascript.
Head over to our practice platform Code360 to practice top problems, attempt mock tests, read interview experiences, and much more!!