Start here. This is the direct spoken answer to practice first.
Why this question matters
Frontend code shares the main thread with user interaction and much of the browser's rendering work. A correct async API can still produce a frozen page when too much JavaScript runs without yielding.
JavaScript runs one stack at a time on the main thread. The browser takes a task such as a click or timer callback, runs it, drains queued microtasks such as resolved promise callbacks, and then gets an opportunity to render before the next task. If a task or a chain of microtasks runs for too long, paint and input handling wait. That is why a CPU-heavy loop blocks the UI even when it started inside an async function.