Skip to main content

Event Loop

Updated 3 min read

Share this page

Send the link, quote the definition with a link back, or show it as a card on your own site.

https://softwaredictionary.org/terms/event-loop

In short

The event loop is a mechanism that lets a single thread handle many tasks by running callbacks one at a time as events and I/O results become ready.

What is the event loop?

The event loop is the part of a runtime that decides which piece of code runs next. In JavaScript, both in browsers and in Node.js, your code runs on a single main thread, so only one piece of JavaScript executes at a time. Instead of waiting for slow operations like network requests, timers, or file reads, the runtime starts them in the background, and the event loop runs the matching callback once the result is ready.

It works together with a call stack and task queues. The call stack holds the functions that are currently running; when it is empty, the event loop first runs every pending microtask, such as resolved promise callbacks and code after an await, and then takes the next task, sometimes called a macrotask, such as a setTimeout callback or an incoming network event. In Node.js the loop cycles through fixed phases for timers, I/O callbacks, and setImmediate, and a library called libuv handles the waiting underneath.

Picture a single chef who starts the pasta boiling, sets a timer, and chops vegetables while waiting, reacting to each timer as it goes off instead of staring at the pot. This design is why a Node.js server can handle thousands of concurrent connections with one thread and why browsers stay responsive while waiting for data. Similar loops power Python's asyncio, desktop GUI toolkits, and game engines.

The event loop is often misunderstood as running JavaScript in parallel. It provides concurrency, meaning many tasks make progress by taking turns, not parallelism, meaning tasks running at the same instant on different CPU cores. A long synchronous task, such as a huge loop or parsing a giant JSON file, blocks the loop, so timers fire late and a server stops responding until it finishes, which is why such work should be split up or moved to worker threads.

At a glance

The event loop: code on the call stack starts slow work in the background; finished callbacks wait in the task queue and promise callbacks in the microtask queue, and whenever the stack is empty the loop runs all microtasks first, then the next task.starts slow workwhen ready1 · all microtasks2 · then one taskwhen stack is emptyCall stackcallback()Background (Web APIs)timers, network requests, file readsMicrotask queuepromise callbacks, awaitTask queuesetTimeout, eventsEvent loop
One thread, one thing at a time: the loop hands over a callback only when the stack is empty, and microtasks always go before the next task.

Key takeaways

  • The event loop runs callbacks one at a time on a single thread.
  • Slow I/O happens in the background, so the thread never sits idle waiting.
  • Microtasks, like promise callbacks, run before the next task, like a setTimeout callback.
  • It provides concurrency, not parallelism.
  • Long synchronous code blocks the loop and freezes everything else.

Example

The order in which the event loop runs codejavascript
console.log("1: synchronous code runs first");

setTimeout(() => console.log("4: timer callback (a task)"), 0);

Promise.resolve().then(() => console.log("3: promise callback (a microtask)"));

console.log("2: still synchronous");

// Output order: 1, 2, 3, 4
// Even a 0 ms timer waits until the call stack is empty
// and every pending microtask has run.

Readers ask

Is JavaScript single-threaded?

JavaScript code runs on a single main thread, and the event loop schedules everything that runs on it. The runtime itself uses other threads for work like networking and file I/O, and you can create more with web workers in browsers or worker_threads in Node.js.

What is the difference between microtasks and macrotasks?

Microtasks, such as promise callbacks and queueMicrotask(), run as soon as the current code finishes, and all of them run before anything else. Macrotasks, such as setTimeout, setInterval, and I/O callbacks, run one per turn of the event loop, after the microtask queue is empty.

What does blocking the event loop mean?

It means running synchronous code that takes so long that the event loop can't process anything else, such as incoming requests, timers, or clicks. Break the work into smaller pieces, use asynchronous APIs, or move it to a worker thread.

See also

Sources

Spotted a mistake or something missing on this page?Suggest an edit

Read a random page
Open today's review
Switch to the dark theme
Read this page in Türkçe

More

Settings