Question presented to candidate: "Walk me through what the call stack, the event loop, and the task queues actually are, and how they work together when JavaScript runs asynchronous code."
What a strong answer should cover:
- The call stack is a real, finite, last-in-first-out (LIFO) structure of function frames -- the innermost call always finishes before the call that made it resumes.
- JavaScript is single-threaded: only one frame executes at a time, so a long-running synchronous function blocks everything else, including timers and promise callbacks.
- The event loop is the mechanism that, once the call stack is completely empty, checks the microtask queue (fully drains it), then runs exactly one macrotask, then repeats.
- Two separate queues exist for queued async work: the microtask queue (Promise reactions, queueMicrotask) and the macrotask/task queue (setTimeout, setInterval, I/O, UI events).
- A callback in either queue can only start running once the call stack is empty -- queued work never interrupts currently running synchronous code.
Clarifying questions expected:
- "Do you want the browser event loop specifically, or should I also mention how Node.js differs (for example process.nextTick)?"
Code / implementation expected: Yes -- a short, runnable snippet demonstrating that a synchronous busy loop delays both a queued timer and a queued microtask.