🕒 Understanding the Event Loop and Concurrency Model in JavaScript
Tags: javascript, eventloop, webdev, programming
Published: 2024-06-20 02:18:25

JavaScript is single-threaded, but it manages to handle asynchronous operations seamlessly. The magic behind this is the Event Loop. In this blog, we'll dive deep into how the Event Loop works and how JavaScript handles concurrency. 🧙‍♂️

please subscribe to my [YouTube channel](https://www.youtube.com/@DevDivewithDipak?sub_confirmation=1
) to support my channel and get more web development tutorials.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2y0v4cy0w8pvuk59xv8.png)

### 📜 Table of Contents
1. [Introduction](#introduction)
2. [Call Stack](#call-stack)
3. [Web APIs](#web-apis)
4. [Callback Queue](#callback-queue)
5. [Event Loop](#event-loop)
6. [Microtasks and Macrotasks](#microtasks-and-macrotasks)
7. [A Simple Example](#a-simple-example)
8. [Conclusion](#conclusion)

### 📚 Introduction <a name="introduction"></a>
JavaScript’s concurrency model is based on an event loop, which allows it to perform tasks asynchronously, even though it runs on a single thread. This means it can handle many tasks at the same time without waiting for one to finish before starting another.

### 🏗️ Call Stack <a name="call-stack"></a>
The call stack is a simple data structure that keeps track of function calls. Think of it as a pile of books where you can only add or remove the book on top.

When a function is called, it’s added to the stack. When the function execution is complete, it’s removed from the stack.

```javascript
function foo() {
  console.log('foo');
}

function bar() {
  foo();
  console.log('bar');
}

bar();
```
- When `bar()` is called, it goes on top of the stack.
- Inside `bar()`, `foo()` is called, so it’s placed on top of `bar()`.
- When `foo()` finishes, it’s removed from the stack, and `bar()` continues.

### 🌐 Web APIs <a name="web-apis"></a>
JavaScript in browsers provides Web APIs for handling tasks like `setTimeout`, `fetch`, and DOM events. These APIs run in the background and, when tasks are completed, their callbacks are added to the Callback Queue.

### 🔃 Callback Queue <a name="callback-queue"></a>
The Callback Queue (also known as the Task Queue) is where asynchronous callbacks from Web APIs wait to be executed. 

When the call stack is empty, the Event Loop picks the first task from the Callback Queue and puts it on the call stack for execution.

### 🔄 Event Loop <a name="event-loop"></a>
The Event Loop is like a manager who keeps an eye on the call stack and the Callback Queue. Here’s how it works:
1. The Event Loop looks at the call stack to see if it’s empty.
2. If the stack is empty, it takes the first task from the Callback Queue and puts it on the stack.
3. The task runs and is then removed from the stack.
4. This process repeats.

### 🧩 Microtasks and Macrotasks <a name="microtasks-and-macrotasks"></a>
Tasks in JavaScript are divided into two categories: macrotasks and microtasks.

- **Macrotasks**: These include `setTimeout`, `setInterval`, and I/O operations. They are placed in the Callback Queue.
- **Microtasks**: These include `Promise` callbacks and `MutationObserver`. They are placed in the Microtask Queue.

Microtasks have a higher priority than macrotasks. They are executed right after the current task completes, before any macrotasks.

### 👨‍💻 A Simple Example <a name="a-simple-example"></a>
Let’s look at an example to see this in action:

```javascript
console.log('Start');

setTimeout(() => {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise');
}).then(() => {
  console.log('Another Promise');
});

console.log('End');
```

**Step-by-Step Execution:**
1. `console.log('Start')` is added to the stack and runs immediately, logging "Start".
2. `setTimeout` is called, which registers a task in the Web API to run after 0ms. Its callback is placed in the Callback Queue.
3. `Promise.resolve().then(...)` creates a microtask. The callback for this microtask is placed in the Microtask Queue.
4. `console.log('End')` is added to the stack and runs immediately, logging "End".

At this point, the stack is empty. The Event Loop checks the Microtask Queue first:
5. The first promise callback runs, logging "Promise".
6. The second promise callback runs, logging "Another Promise".

Finally, the Event Loop checks the Callback Queue:
7. The `setTimeout` callback runs, logging "setTimeout".

**Output:**
```
Start
End
Promise
Another Promise
setTimeout
```

### 🏁 Conclusion <a name="conclusion"></a>
Understanding the Event Loop and Concurrency Model is essential for writing efficient JavaScript code. By mastering these concepts, you can handle asynchronous operations better and build more responsive applications. 🌟

### 🚀 Happy Coding!

Feel free to leave your comments or questions below. If you found this guide helpful, please share it with your peers and follow me for more web development tutorials. Happy coding!

### Follow and Subscribe:
- **Instagram**: [devdivewithdipak](https://www.instagram.com/devdivewithdipak)
- **Website**: [Dipak Ahirav] (https://www.dipakahirav.com)
- **Email**: dipaksahirav@gmail.com
- **YouTube**: [devDive with Dipak](https://www.youtube.com/@DevDivewithDipak?sub_confirmation=1
)
- **LinkedIn**: [Dipak Ahirav](https://www.linkedin.com/in/dipak-ahirav-606bba128)