Back to JavaScript Notes
Topic #415

The Event Loop

You will be able to explain how JavaScript runs asynchronous code on one thread by using the event loop, microtasks, and macrotasks.

What it is

JavaScript runs on a single main thread. That means only one piece of JavaScript can execute at a time. The event loop is the mechanism that lets JavaScript handle asynchronous work without blocking that thread.

A useful mental model is:

  • The call stack runs synchronous code.
  • Browser or Node APIs handle asynchronous work outside the main thread.
  • When that work finishes, a callback is placed in a queue.
  • The event loop moves callbacks from queues to the call stack when the stack is empty.

There are two important queues:

  • Microtasks: small, high-priority tasks such as Promise.then() callbacks and async/await continuations.
  • Macrotasks: larger tasks such as setTimeout(), setInterval(), I/O callbacks, and user events.

Related terms include call stack, task queue, microtask queue, Promise, and async/await.

Why it matters

  • It explains why long synchronous loops can freeze a browser page.
  • It helps you predict the order of asynchronous callbacks.
  • It shows why Promise.then() can run before setTimeout().
  • It helps you choose the right scheduling tool for responsive UI code.
  • It prevents mistakes like accidentally starving the event loop with recursive microtasks.

Syntax or steps

The smallest useful pattern is to understand the order of execution:

  1. Run all synchronous code first.
  2. When the call stack is empty, run all available microtasks.
  3. Run one macrotask.
  4. Run all microtasks again.
  5. Repeat.

For example, schedule a microtask with:

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

Schedule a macrotask with:

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

Example

console.log('start');

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

Promise.resolve().then(() => console.log('promise'));

console.log('end');

Expected output:

start
end
promise
timeout

Part-by-part explanation:

  • console.log('start') runs immediately because it is synchronous.
  • setTimeout() schedules a macrotask. Even with 0, it does not run immediately.
  • Promise.resolve().then() schedules a microtask.
  • console.log('end') runs immediately because it is synchronous.
  • After the synchronous code finishes, the event loop drains the microtask queue, so promise logs next.
  • Then the event loop takes one macrotask, so timeout logs last.

Common mistakes

  • Assuming setTimeout(fn, 0) runs immediately. It only runs after the current synchronous code and all microtasks finish.
  • Thinking await blocks the thread. It pauses the async function and schedules its continuation as a microtask.
  • Using recursive microtasks for long work. This can prevent rendering and make the UI unresponsive. Use setTimeout() or requestAnimationFrame() when you need to yield.
  • Forgetting that I/O callbacks are macrotasks. Promise continuations may run before network or timer callbacks.

When to use it

Use the event loop model when you need to understand or control asynchronous ordering. The closest practical comparison is between microtasks and macrotasks.

Need Use Why
Run immediately after current code Microtask: Promise.then() or queueMicrotask() Microtasks run before the next macrotask.
Yield to the browser Macrotask: setTimeout() Allows the event loop to process other tasks and render.
Repeat work periodically Macrotask: setInterval() Each interval callback is queued as a new task.
Handle user events or I/O Macrotask These are normal asynchronous tasks managed by the environment.

Use microtasks for small continuations. Use macrotasks when you need to give the browser a chance to breathe.

Practice

Guided exercise: predict the output of this code.

setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('A'));
console.log('C');

Expected output:

C
A
B

Challenge: write code that logs 1, 2, 3, 4 in that order using one synchronous log, one microtask, and one macrotask.

Solution hint: put 1 in synchronous code, 2 in a Promise.then(), and 3 or 4 in a setTimeout().

Quick check

Question: If a setTimeout() callback and a Promise.then() callback are scheduled in the same synchronous block, which runs first?

Answer: The Promise.then() callback runs first because microtasks are processed before macrotasks.

Summary

JavaScript uses one main thread, and the event loop schedules asynchronous work by moving callbacks from queues onto the call stack. Microtasks run before macrotasks, which is why promise continuations often appear before timer callbacks.

Want to go beyond the notes?

Join Coding Now Tech Institute's JavaScript course — live mentorship, real projects, and 100% placement support.

Enroll Now — Free Demo Available

The Event Loop – FAQs

Quick answers about learning The Event Loop in JavaScript.

This free note from Coding Now Tech Institute explains The Event Loop in JavaScript — concept, syntax and worked code examples you can copy, run and revise before interviews.
Yes. Every JavaScript topic on Coding Now Tech Institute, including The Event Loop, is 100% free with no signup required.
With focused practice, most students grasp The Event Loop in 1–3 days from these notes; pairing it with Coding Now Tech Institute's mentor-led course takes you to job-ready depth faster.
Use the code examples in this note, then ask doubts for free on the Coding Now Tech Institute Community (/community) — expert instructors answer within 24 hours.
Call NowEnroll Now