A callback is a function you pass to other code to call later: array.map(fn) calls it synchronously, while setTimeout(fn) and addEventListener("click", fn) call it after your current code finishes. The engine (V8 86,723 , SpiderMonkey 946,470 , JavaScriptCore) runs code on a call stack; the host (the browser, or Node.js 2,131 with libuv) waits for timers, sockets and disks, often on other threads, and queues your callback when the result is ready. The event loop picks what runs next.

A task runs to completion, so while your code is busy nothing else happens: no timer, no click, no repaint.
const start = performance.now();
setTimeout(() => console.log(`0 ms timer ran after ${Math.round(performance.now() - start)} ms`));
while (performance.now() - start < 200) {} // 200 ms of work blocks the call stack
console.log("busy loop done");busy loop done 0 ms timer ran after 202 ms
The setTimeout() delay (Timers) is only a minimum. Browsers flag tasks of 50 ms or more as long tasks (Long Tasks API, DevTools Performance panel) because they delay input. Split heavy work into chunks separated by timers, or move it to a Web Worker (Web APIs), which has its own event loop. Node.js runs the same model in phases: timers, I/O polling, setImmediate() checks and close callbacks.