Explain the Event Loop and Execution Order in JavaScript

Understand how JavaScript handles tasks, microtasks, and macrotasks — and how to control async execution order effectively.

intermediateAsync and promisesjavascriptevent looppromisesmicrotasksmacrotasks
Published: 11/12/2025
Updated: 11/12/2025

Advertisement

Question

You have the following code:

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

What will be the output and why?
Then, modify the code so that B prints before C — without blocking the thread.


Explanation

Let’s visualize what happens in the JavaScript Event Loop:

sequenceDiagram participant Script participant CallStack participant MicrotaskQueue participant MacrotaskQueue Script->>CallStack: console.log('A') CallStack-->>Script: Prints 'A' Script->>MacrotaskQueue: setTimeout(callback) Script->>MicrotaskQueue: Promise.then(callback) Script->>CallStack: console.log('D') CallStack-->>Script: Prints 'D' MicrotaskQueue-->>CallStack: Run Promise callback (Print 'C') MacrotaskQueue-->>CallStack: Run Timeout callback (Print 'B')

Output order:

A
D
C
B

That’s because:

  • Microtasks (Promises) always run before macrotasks (setTimeout)
  • JS runs all microtasks right after the current call stack empties

To Make B Print Before C

You can use a microtask scheduling trick:

console.log('A');
queueMicrotask(() => console.log('B')); // executes before Promises
Promise.resolve().then(() => console.log('C'));
console.log('D');

Output now:

A
D
B
C

or, force B to occur before Promise by:

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

Real-World Example

  • Animations that must occur after paint but before next Promise chain
  • Sequencing API calls with microtasks to ensure immediate but non-blocking behavior
  • Debugging “why my Promise executes before my setTimeout”

Quick Practice

👉 Try modifying the snippet to include:

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

and predict the new order.
Explain using the event loop phases.


Summary

  • The event loop runs synchronously → microtasks → macrotasks.
  • Promises (microtasks) always win over setTimeout.
  • To manage order, use:
    • queueMicrotask() for early callbacks
    • setImmediate() (Node.js) or chained promises for controlled timing
    • Understanding these distinctions is key for async debugging.
Related Videos
Watch these videos to learn more about this topic
Frequently Asked Questions

Can setTimeout(…, 0) execute before Promise callbacks?

No. Promise microtasks always run before macrotasks like setTimeout.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement