Once people study asynchronous JavaScript for a while, they eventually run into the event loop. Even after using Promise, setTimeout, and async/await, it is still common to wonder why some code runs immediately while other code runs later.
The event loop is what starts making that timing feel less mysterious. It helps answer the question: if JavaScript seems to run one thing at a time, how does asynchronous behavior still work?
This post covers three things.
- what the event loop is
- what the call stack and queues do
- why asynchronous code appears to run later
The key idea is this: the event loop is the coordination mechanism that moves ready asynchronous work onto the call stack at the right time.
Why the event loop matters
JavaScript often looks single-threaded from the way code is written. But even so, all of these seem to happen naturally:
setTimeout- click events
- network response handling
- Promise continuations
To understand that behavior clearly, the event loop matters.
The basic pieces
At a beginner level, three concepts are enough to start:
- call stack
- queue
- event loop
1. Call stack
This is where currently executing functions live. JavaScript usually runs whatever is on top of this stack.
2. Queue
This is where later work waits. Timers, events, and Promise continuations can end up in waiting structures before they are ready to run.
3. Event loop
The event loop checks whether the call stack is free enough to take more work, and if so, moves queued work into execution.
So a good mental model is: the event loop decides when waiting work gets its turn.
A simple example
console.log('A');
setTimeout(() => {
console.log('B');
}, 0);
console.log('C');
Many beginners expect A, B, C, but the usual result is:
A
C
B
That happens because the timeout callback does not go straight onto the call stack. It becomes eligible later, and only runs after the current stack work is done.
Why Promise often looks different
Promise.then() and await continuations often appear to run before timer callbacks. The fully detailed explanation involves microtasks and macrotasks, but at a beginner level it is enough to understand that not all queued asynchronous work has the same priority.
For example:
console.log('start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');
A common result is:
start
end
promise
timeout
So asynchronous work is not all scheduled in exactly the same way.
How async/await relates to the event loop
When await appears, the current async function pauses its local flow, and the remaining continuation resumes later through Promise-based scheduling.
That is why async/await can look synchronous while still depending on the event loop and Promise scheduling behavior underneath.
Common misunderstandings
1. setTimeout(fn, 0) means immediate execution
Not exactly. It means the callback becomes eligible after current stack work is done, not that it jumps ahead instantly.
2. The event loop directly performs all asynchronous work itself
It is better to think of it as a coordinator of execution timing rather than the thing performing every external operation.
3. If I use async/await, I do not need to understand the event loop
The syntax gets easier, but execution order questions still lead back to the event loop.
A good beginner exercise
- run examples with
console.logandsetTimeout - add Promise examples and compare the order
- rewrite the same flow with
async/await - compare expected order with actual order
This makes the event loop much easier to understand through observation rather than only theory.
FAQ
Q. Is the event loop only a browser concept?
No. It also matters in runtimes like Node.js.
Q. Why do Promise and setTimeout seem to run in different orders?
Because different kinds of queued work may be handled with different priority rules.
Q. Do I need a perfect event loop model before writing async code?
Not at first. But when execution order feels surprising, the event loop is exactly the concept that helps.
Read Next
- If you want the async syntax side again, pair this with Promise and async/await Guide.
- If you want to revisit the bigger conceptual difference first, Synchronous vs Asynchronous Guide is a strong starting point.
While AdSense review is pending, related guides are shown instead of ads.
Start Here
Continue with the core guides that pull steady search traffic.
- Middleware Troubleshooting Guide: Redis vs RabbitMQ vs Kafka A practical middleware troubleshooting guide for developers covering when to reach for Redis, RabbitMQ, or Kafka symptoms first, and which problem patterns usually belong to each tool.
- Kubernetes CrashLoopBackOff: What to Check First A practical Kubernetes CrashLoopBackOff troubleshooting guide covering startup failures, probe issues, config mistakes, and what to inspect first.
- Kafka Consumer Lag Increasing: Troubleshooting Guide A practical Kafka consumer lag troubleshooting guide covering what lag usually means, which consumer metrics to check first, and how poll timing, processing speed, and fetch patterns affect lag.
- Kafka Rebalancing Too Often: Common Causes and Fixes A practical Kafka troubleshooting guide covering why consumer groups rebalance too often, what poll timing and group protocol settings matter, and how to stop rebalances from interrupting useful work.
- Docker Container Keeps Restarting: What to Check First A practical Docker restart-loop troubleshooting guide covering exit codes, command failures, environment mistakes, health checks, and what to inspect first.
While AdSense review is pending, related guides are shown instead of ads.