"Asynchronous" in JavaScript doesn't mean "runs on another thread" — it means "runs later, after the current synchronous code has finished, scheduled by the browser/runtime rather than by the normal call stack."
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
// Output: 1, 3, 2 — even a 0ms timeout is scheduled for LATER, never immediately
setTimeout(fn, 0) doesn't mean "run in 0 milliseconds" — it means "run as soon as possible after the current synchronous code finishes and the stack is empty," which is a fundamentally different guarantee. This single fact explains a large share of async confusion: synchronous code always finishes completely before any scheduled callback gets a chance to run, no matter how small its delay.