Explain how the JavaScript event loop works. What's the difference between microtasks and macrotasks?

3 minintermediatejavascripteventloopworks

Quick Answer

The JavaScript event loop is the mechanism that allows JavaScript to handle asynchronous operations despite being single-threaded.

Detailed Answer

Explain how the JavaScript event loop works. What's the difference between microtasks and macrotasks?

Answer: The JavaScript event loop is the mechanism that allows JavaScript to handle asynchronous operations despite being single-threaded. Here's how it works:

Components:

  • Call Stack: Executes synchronous code (LIFO - Last In, First Out)
  • Web APIs: Browser APIs for timers, DOM events, HTTP requests
  • Task Queue (Macrotask Queue): For callbacks from setTimeout, setInterval, DOM events
  • Microtask Queue: For callbacks from Promises, queueMicrotask, MutationObserver

Execution Flow:

  1. Execute all synchronous code in the call stack
  2. When call stack is empty, process ALL microtasks first
  3. Then process ONE macrotask
  4. Repeat

Microtasks vs Macrotasks:

  • Microtasks (higher priority): Promise callbacks (.then, .catch, .finally), queueMicrotask(), MutationObserver callbacks
  • Macrotasks (lower priority): setTimeout/setInterval callbacks, DOM event callbacks, I/O operations

Example:

console.log('1'); // Synchronous
setTimeout(() => console.log('2'), 0); // Macrotask
Promise.resolve().then(() => console.log('3')); // Microtask
console.log('4'); // Synchronous
// Output: 1, 4, 3, 2

Follow-up: How would you handle a situation where you need to execute multiple async operations in parallel but want to wait for all of them to complete?

Answer: Use Promise.all() for parallel execution with all-or-nothing behavior, or Promise.allSettled() for handling individual failures:

// All-or-nothing approach
async function fetchMultipleData() {
  try {
    const [users, posts, comments] = await Promise.all([
      fetch('/api/users').then(res => res.json()),
      fetch('/api/posts').then(res => res.json()),
      fetch('/api/comments').then(res => res.json())
    ]);
    return { users, posts, comments };
  } catch (error) {
    console.error('One or more requests failed:', error);
    throw error;
  }
}

// Handle individual failures
async function fetchWithFallback() {
  const results = await Promise.allSettled([
    fetch('/api/users').then(res => res.json()),
    fetch('/api/posts').then(res => res.json()),
    fetch('/api/comments').then(res => res.json())
  ]);
  
  return results.map((result, index) => {
    if (result.status === 'fulfilled') {
      return result.value;
    } else {
      console.error(`Request ${index} failed:`, result.reason);
      return null; // or default value
    }
  });
}