DEV Community

Cover image for 🔥JavaScript Interview Series(14): Event Loop, Microtasks & Macrotasks Deep Dive
jackma
jackma

Posted on

🔥JavaScript Interview Series(14): Event Loop, Microtasks & Macrotasks Deep Dive

The JavaScript Event Loop is one of the most misunderstood yet fundamental concepts that every developer must master. It dictates how asynchronous code is executed, how promises are resolved, and how tasks are prioritized. In this article, we’ll go through 10 real interview questions with professional explanations, examples, and follow-up questions designed to test your true understanding.


1. (Interview Question 1) What is the Event Loop in JavaScript?

Key Concept: Core mechanism of asynchronous execution

Model Answer:
The Event Loop is a mechanism that allows JavaScript to perform non-blocking operations despite being single-threaded. It continuously checks the call stack and the task queues (macrotasks and microtasks). When the call stack is empty, the event loop takes tasks from the queue and pushes them onto the stack for execution.

A simplified pseudo-code representation:

while (true) {
  if (callStack.isEmpty()) {
    executeNextTaskFromQueue();
  }
}
Enter fullscreen mode Exit fullscreen mode

Key insight: Microtasks (like Promise.then) run before the next macrotask (like setTimeout).

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. How does the event loop differ in Node.js vs browsers?
  2. Why doesn’t JavaScript block during network requests?
  3. Can you simulate a blocking operation in JS?

2. (Interview Question 2) What are microtasks and macrotasks in JavaScript?

Key Concept: Task prioritization and timing

Model Answer:
Microtasks are queued for execution after the current script and before the next rendering phase. They include operations like Promise.then, queueMicrotask, and process.nextTick (Node.js).
Macrotasks include events like setTimeout, setInterval, setImmediate, and DOM events.

Order of execution:

  1. Execute current script
  2. Run all microtasks
  3. Render updates
  4. Execute next macrotask

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Why do Promises resolve before setTimeout callbacks?
  2. How does Node.js handle microtasks differently from browsers?
  3. What happens if a microtask enqueues another microtask?

3. (Interview Question 3) What is the output of this code and why?

Key Concept: Promise resolution order

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

Model Answer:
Output:

A  
D  
C  
B
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • A and D run first (synchronous).
  • Then Promise.then (microtask) runs before the next macrotask (setTimeout).
  • So C prints before B.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. How would the order change if you use await instead?
  2. What if the timeout was set to setTimeout(..., 100)?
  3. How can you delay microtasks execution intentionally?

4. (Interview Question 4) Explain the difference between process.nextTick() and Promises in Node.js.

Key Concept: Node.js event loop phases

Model Answer:
In Node.js, process.nextTick() queues callbacks before the event loop continues to the next phase, meaning it runs before any microtask or I/O callback.
Promise.then is queued in the microtask queue, which runs after the current phase but before timers or I/O callbacks.

Thus, process.nextTick() has higher priority and can block the event loop if used recursively.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. What phase runs after process.nextTick()?
  2. Why should you avoid using process.nextTick() too frequently?
  3. Can process.nextTick() starve I/O operations?

5. (Interview Question 5) How does async/await interact with the event loop?

Key Concept: Promises and microtasks

Model Answer:
When an async function is called, it returns a Promise immediately. Each await pauses the function’s execution until the awaited Promise resolves, but it doesn’t block the thread — instead, the remaining part of the function is queued as a microtask.

Example:

async function test() {
  console.log('1');
  await Promise.resolve();
  console.log('2');
}
test();
console.log('3');
Enter fullscreen mode Exit fullscreen mode

Output: 1 3 2

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Can await be used outside an async function?
  2. How is await different from Promise.then?
  3. What happens if the awaited Promise rejects?

6. (Interview Question 6) What happens when a microtask queues another microtask inside itself?

Key Concept: Microtask recursion

Model Answer:
Microtasks execute until the queue is empty before moving to the next macrotask.
If a microtask enqueues another microtask, that new one will be executed in the same cycle, potentially causing infinite loops and blocking rendering.

Example:

Promise.resolve().then(function loop() {
  console.log('loop');
  Promise.resolve().then(loop);
});
Enter fullscreen mode Exit fullscreen mode

This will keep running endlessly and block rendering.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Why doesn’t this crash immediately?
  2. How can you prevent infinite microtask loops?
  3. What’s the difference if you use setTimeout(loop, 0) instead?

7. (Interview Question 7) How does rendering fit into the Event Loop?

Key Concept: Browser rendering cycle

Model Answer:
After executing all microtasks, the browser may perform layout and paint operations before executing the next macrotask. This ensures UI updates happen between task cycles and not mid-cycle, preserving a consistent visual state.

Insight: Too many microtasks can delay rendering, causing UI freezes.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. How can long microtask chains affect FPS?
  2. What strategies can improve rendering performance?
  3. Does requestAnimationFrame run as a microtask or macrotask?

8. (Interview Question 8) Explain the execution order in this example:

Key Concept: Interleaving microtasks and macrotasks

setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
queueMicrotask(() => console.log('microtask'));
console.log('script');
Enter fullscreen mode Exit fullscreen mode

Model Answer:
Output:

script  
promise  
microtask  
timeout
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Synchronous code first (script)
  • Then all microtasks (promise, microtask)
  • Then macrotasks (timeout)

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Is the order between Promise and queueMicrotask guaranteed?
  2. What would happen if you nest a Promise inside another Promise?
  3. How can you flush all microtasks manually?

9. (Interview Question 9) How does Node.js schedule timers like setTimeout?

Key Concept: Node.js event loop phases and timers

Model Answer:
In Node.js, timers are executed in the timers phase of the event loop. If the specified delay has elapsed, their callback runs; otherwise, they wait until the next iteration.
However, actual timing is not guaranteed — it depends on other tasks and I/O operations in the loop.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Why might a setTimeout(fn, 0) not run immediately?
  2. What happens if the event loop is busy with CPU work?
  3. How does setImmediate differ from setTimeout(fn, 0)?

10. (Interview Question 10) How would you explain the event loop to a non-technical person?

Key Concept: Communication and abstraction skills

Model Answer:
Imagine a chef (JavaScript) working alone in a kitchen. The chef takes one order (task) at a time from the counter (call stack). If an order needs to “wait” (like baking), the chef sets a timer (macrotask) and moves on to the next order. When the baking is done, the timer reminds the chef to continue. Small tasks like checking ingredients (microtasks) happen between main orders.

This analogy helps explain why JavaScript appears “asynchronous” but is still single-threaded.

Possible Follow-up Questions: 👉 (Want to test your skills? Try a Mock Interview — each question comes with real-time voice insights)

  1. Can you extend this analogy to explain Promises?
  2. How would you explain blocking I/O in this analogy?
  3. How does this model impact performance optimization?

Final Note:
Mastering the Event Loop, Microtasks, and Macrotasks is not just about memorizing order — it’s about understanding how JavaScript achieves concurrency within a single thread. Interviewers often probe this area deeply because it reveals how well you truly understand asynchronous behavior and performance tuning.

Top comments (0)