The JavaScript event loop lets the system do the waiting for async work, then runs each callback on its one thread. It takes the next callback from a queue, runs it to completion, then grabs the next.
When you start a timer, network request, or file read, the runtime hands it to the system or a background pool. Your thread moves on right away.
When the operation finishes, its callback joins a queue. The loop runs it only after the current work returns and the stack is empty. So a ready callback still waits behind the running code.
This model avoids locks, since only one callback runs at a time. The catch is that any slow synchronous function freezes everything. One blocking loop stalls every pending timer, request, and click.
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.
Why there's no diagram: “”
The interactive diagram is below the answer - jump to diagram ↓ · Below it, the related concept . Jump to it ↓
The diagram below the answer is the concept . Jump to it ↓