Task Queue
The task queue holds callbacks from asynchronous operations that are ready to run once the current JavaScript execution stack has finished. The event loop takes tasks and executes them one at a time, while microtasks have priority before the next task begins.
A task is a unit of work scheduled by the JavaScript environment, such as a timer callback, user interaction handler, or certain I/O-related callbacks. When a task becomes eligible, its callback can be placed into a task queue until the event loop can process it.
JavaScript executes synchronous code on the call stack. The event loop can take a queued task and place its callback onto the stack only when the stack is empty, so queued work does not interrupt currently executing synchronous code.
The task queue is distinct from the microtask queue. After a task finishes, the runtime processes pending microtasks, such as promise reactions, before moving on to another task. This means a microtask can run before a task that was already waiting in the task queue.
Browsers can also perform rendering between event-loop turns when appropriate. Therefore, code that repeatedly schedules tasks can yield control between pieces of work, whereas a long-running synchronous task blocks JavaScript execution and can delay input handling and rendering.
Key points
- Tasks run only after the current call stack becomes empty.
- Timers and user-event callbacks are common sources of tasks.
- The task queue is separate from the microtask queue.
- Microtasks are processed before the event loop proceeds to another task.
- A long-running task can block input, rendering, and other JavaScript work.
Interview questions
What does `setTimeout(fn, 0)` actually guarantee?
It does not guarantee that `fn` executes immediately or exactly zero milliseconds later. It requests that the callback become eligible after the specified delay. The callback still has to wait for currently executing JavaScript and other event-loop work. Consequently, the actual execution time can be later than the requested delay.
What is the task queue in JavaScript?
The task queue contains callbacks that are ready to execute but are waiting for the JavaScript runtime to process them. Examples include many timer callbacks and user-event handlers. The event loop takes a task when the current execution stack is empty. The callback then runs as normal JavaScript on the call stack.
What is the difference between a task and a microtask?
They are different categories of queued asynchronous work. A task is processed as an event-loop task, while a microtask is normally processed after the current task completes. Pending microtasks are drained before the runtime proceeds to another task. Promise reactions are a common source of microtasks.
What happens when a task runs for a long time in a browser?
The JavaScript execution remains occupied while that task runs. Other JavaScript callbacks cannot execute during that time, and the browser may also be unable to respond promptly to user input or update rendering. This is why expensive synchronous work can cause a page to feel unresponsive. Splitting suitable work into smaller units can allow the browser more opportunities to handle other work.
Predict the output when a timer and a resolved Promise are scheduled in the same script.
The synchronous statements execute first because they are already running on the call stack. The resolved Promise schedules a microtask, while the timer schedules a task. After the current task finishes, the runtime drains the microtask queue before taking another task. Therefore, the Promise callback normally runs before the timer callback.