My JavaScript Learning Journey: JavaScript 이벤트 루프 및 동시성 모델 이해

작성자

카테고리:

← 피드로
DEV Community · HARSHITH GADDAM · 2026-07-21 개발(SW)

Today, I learned one of the most important concepts in JavaScript: the Event Loop and the Concurrency Model.

JavaScript is Single-Threaded

JavaScript is a single-threaded language. This means it can execute only one piece of JavaScript code at a time.

For example:

console.log(“A”);
console.log(“B”);
console.log(“C”);

Output:

A
B
C

JavaScript executes these statements one after another.

What is the Call Stack?

The Call Stack is where JavaScript executes functions. Whenever a function is called, it is added to the stack. After the function finishes executing, it is removed from the stack.

Example:

function one() {
two();
}

function two() {
console.log(“Hello”);
}

one();

Execution order:

one()

two()

console.log()

Stack becomes empty

The Call Stack follows the Last In, First Out (LIFO) principle.

What are Web APIs and Node APIs?

Some operations take time, such as:

  • Waiting for a timer
  • Making an API request
  • Reading a file
  • Listening for button clicks

JavaScript itself cannot perform these operations.

Instead, it asks the runtime to handle them.

In Browsers

The browser provides Web APIs such as:

  • setTimeout()
  • setInterval()
  • fetch()
  • addEventListener()
  • DOM APIs
  • localStorage

In Node.js

Node.js provides Node APIs such as:

  • fs.readFile()
  • fs.writeFile()
  • path
  • os
  • http

These APIs perform asynchronous work outside the JavaScript engine.

Callback (Macrotask) Queue

When an asynchronous operation like setTimeout() finishes, its callback does not execute immediately.

Instead, it is placed into the Callback Queue, also called the Macrotask Queue.

Example:

setTimeout(() => {
console.log(“Timer”);
}, 1000);

After one second Call back function added to Callback Queue.
It waits there until the Event Loop moves it to the Call Stack.

Microtask Queue

The Microtask Queue has a higher priority than the Callback Queue.

The following callbacks are added to the Microtask Queue:

  • Promise.then()
  • Promise.catch()
  • Promise.finally()
  • await
  • queueMicrotask()

Example:

Promise.resolve().then(() => {
console.log(“Promise”);
});

The callback is placed in the Microtask Queue.

Event Loop

The Event Loop is responsible for checking whether the Call Stack is empty.

When the Call Stack becomes empty, it:

  1. Executes all Microtasks
  2. Executes one Callback (Macrotask)
  3. Again checks call stack is empty or not and does 1&2.

It does not execute code itself. It simply moves callbacks from the queues to the Call Stack.

Why do Promises execute before setTimeout()?

Consider this example:

console.log(“Start”);

setTimeout(() => {
console.log(“Timeout”);
}, 0);

Promise.resolve().then(() => {
console.log(“Promise”);
});

console.log(“End”);

Output:
Start
End
Promise
Timeout

Why?

  • Promise.then() goes to the Microtask Queue.
  • setTimeout() goes to the Callback (Macrotask) Queue.
  • The Event Loop always executes all Microtasks first before executing Macrotasks.

Does setTimeout() execute exactly on time?

A common misunderstanding is that:

setTimeout(callback, 1000);

means the callback will execute exactly after one second.

This is not true.

It means:

Execute the callback after at least one second.

If the Call Stack is busy with synchronous code, the callback has to wait.

Example:

setTimeout(() => {
console.log(“Done”);
}, 1000);

// Imagine this loop takes 3 seconds
for (let i = 0; i < 1e10; i++) {}

console.log(“Finished”);

Output:
Finished
Done

Even though the timer finished after one second, the callback waited until the Call Stack became empty.

What is the JavaScript Concurrency Model?

JavaScript can execute only one line of code at a time, but it can still handle many asynchronous operations.

For example:

  • A timer can be counting.
  • A network request can be downloading.
  • The browser can listen for button clicks.

All these operations are handled by the browser or Node.js while JavaScript continues executing other code.

When these operations finish, their callbacks are added to the appropriate queue.

This ability to make multiple operations progress during the same period of time is called the Concurrency Model.

Cooperative Concurrency vs True Parallelism

These two terms are often confused.

Cooperative Concurrency

Only one JavaScript task runs at a time.

Tasks take turns executing.

Example:

One chef starts cooking rice, then makes tea while the rice cooks.

The chef is not doing both tasks at the exact same moment, but both tasks are progressing.

JavaScript works like this.

True Parallelism

Multiple tasks execute at the exact same time using different CPU cores or threads.

Example:

  • Chef 1 cooks rice.
  • Chef 2 makes tea.
  • Chef 3 cuts vegetables.

All three are working simultaneously.

Conclusion

Learning the Event Loop and the Concurrency Model helped me understand how JavaScript performs asynchronous operations without blocking the main thread. These concepts explain why Promise callbacks execute before setTimeout(), why timers are not always exact, and how browsers and Node.js work together with JavaScript to build responsive applications.

Understanding these fundamentals is essential for writing efficient JavaScript code.
Thank you for reading! If you’re also learning JavaScript, I hope this summary helps you understand these concepts more clearly. Happy coding!

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다