Urgent.News

What's breaking now, across thousands of outlets.

Tech

JavaScript Event Loop: How Does JavaScript Handle Multiple Tasks?

JavaScript is often called single-threaded . That means it has one main thread and can execute one piece of JavaScript at a time . So here is the obvious question: If JavaScript can do only one thing at a time, how can it handle all of this? API requests Timers Button clicks User input File operations Animations For example: console . log ( " Start " ); setTimeout (() => { console . log ( " Timer…

JavaScript is commonly referred to as single-threaded, meaning it can execute only one piece of JavaScript code at a time using its main thread. Given this limitation, the question arises as to how JavaScript manages to handle multiple tasks simultaneously. These tasks include API requests, timers, button clicks, user input, file operations, and animations.

Consider the following example:

```

console.log("Start");

setTimeout(() => {

console.log("Timer finished");

}, 2000);

console.log("End");

```

The output is:

```

Start

End

Timer finished

```

Why is this the case? If JavaScript had to wait for the timer to finish, the output should have been:

```

Start

Timer finished

End

```

The explanation lies in the Event Loop, one of the most crucial concepts in JavaScript. To fully grasp the Event Loop, we need to understand the entire system, which consists of five components:

1. The Call Stack - Execution Arena

The Call Stack is where JavaScript executes functions. It acts like a stack of tasks, with the last task added being the first one executed. For instance:

```

function first() {

second();

}

function second() {

console.log("Hello");

}

first();

```

The Call Stack processes the functions step by step:

```

Call Stack

first()

second()

console.log("Hello")

```

As each function completes, it is removed from the stack. This synchronous execution of code tasks is why JavaScript is typically synchronous by default.

2. Web APIs - Browser's Asynchronous Powerhouse

The browser offers powerful features called Web APIs, which handle asynchronous work. Some examples include:

```

setTimeout

fetch

DOM events

addEventListener

Geolocation

```

Continuing with our previous example:

```

console.log("Start");

setTimeout(() => {

console.log("Timer finished");

}, 2000);

console.log("End");

```

Here's what happens:

- `console.log("Start")` is pushed onto the Call Stack and executed, producing the output "Start".

- The timer is registered with the browser's Web APIs.

- `console.log("End")` is executed immediately, outputting "End".

3. Callback Queue - Waiting for Asynchronous Completion

Once an asynchronous operation finishes, its callback can be placed into the Callback Queue, also known as the Task Queue. Web APIs handle this queue. For example:

```

setTimeout(() => {

console.log("Timer finished");

}, 2000);

```

After two seconds, the callback `console.log("Timer finished")` is moved into the Callback Queue:

```

Callback Queue

[ console.log("Timer finished") ]

```

The callback cannot execute yet because the Call Stack must be empty.

4. The Event Loop - The Traffic Controller

The Event Loop continuously checks whether the Call Stack is empty. If it is, the Event Loop moves waiting work from the queues (Callback Queue and Microtask Queue) back into the Call Stack. The process can be visualized as:

```

Is Call Stack Empty?

┌────────┴────────┐

No │ Yes

▼ │ ▼

Keep executing Move next task to the Call Stack

```

Thus, the timer flow becomes:

```

setTimeout(...)

Web APIs

Wait 2 seconds

Callback Queue

Event Loop checks Call Stack

Callback executes

```

This is why the callback runs after the specified delay.

5. Microtasks - A Secondary Queue

In addition to the Callback Queue, there is another queue called the Microtask Queue. Microtasks typically include Promise-related callbacks, such as `.then()`, `.catch()`, `.finally()`, and `queueMicrotask()`. For instance:

```

console.log("Start");

Promise.resolve().then(() => {

console.log("Promise");

});

```

The execution order here is:

```

Call Stack

Promise.resolve()

Microtask Queue

[ console.log("Promise") ]

Event Loop checks Call Stack

Call Stack is empty

Callback executes (console.log("Start"))

Microtask Queue processed

Output: Start, Promise

```

The Event Loop handles these microtasks after executing the current stack of tasks (in this case, after "Start"). The "Promise" output follows the "Start" because the microtask queue is processed after the Call Stack is empty.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Friday 28 August →