The Event Loop
The mechanism that lets single-threaded JavaScript still handle timers, promises, and I/O without blocking.
JavaScript runs on one thread — it can only do one thing at a time on the call stack. Things that take time (timers, network requests, promise callbacks) are handed off to Web APIs provided by the browser, not run inline. When they finish, their callback is placed in a queue rather than run immediately. The event loop's entire job is simple: repeatedly check 'is the call stack empty?' — and if so, pull the next task from a queue and run it. Microtasks (promise callbacks) always drain completely before the event loop touches the next macrotask (like a setTimeout callback), even if that timeout was scheduled for 0ms.
setTimeout's callback always goes to the macrotask queue, even with a 0ms delay — it still has to wait for the call stack to empty AND for every microtask to drain first. Promise callbacks are microtasks, which always jump the line ahead of macrotasks.