Promise Jobs (Microtasks)
Promise fulfillment and rejection handlers are scheduled as microtasks, so they do not run immediately when a promise settles. The JavaScript runtime processes these jobs after the current synchronous work finishes, before moving on to the next task such as a timer.
A Promise reaction is created when you attach handlers with `.then()`, `.catch()`, or `.finally()`. When the associated promise settles, the handler is queued for asynchronous execution rather than called during the current synchronous statement.
These queued reactions are commonly called promise jobs or microtasks. The important interview distinction is that a promise handler is not a timer callback: after the current call stack becomes empty, pending microtasks are processed before the event loop proceeds to another task.
Because microtasks run before the next task, a promise callback can execute before a `setTimeout(..., 0)` callback registered earlier. This ordering explains many event-loop questions involving promises and timers.
Microtasks can also enqueue more microtasks. The runtime continues processing the microtask queue until it is empty before proceeding to the next task, so excessive microtask scheduling can delay timers, rendering, or other work.
Key points
- Promise handlers run asynchronously as microtasks after the current synchronous code completes.
- A settled promise queues its reaction rather than invoking the handler synchronously.
- Microtasks are processed before the event loop moves to the next task.
- A microtask can enqueue another microtask, extending the current microtask checkpoint.
- Promise jobs are distinct from task callbacks such as `setTimeout` callbacks.
Interview questions
When does a `.then()` callback run?
A `.then()` callback does not run synchronously when it is registered. When the promise settles, its reaction is scheduled as a microtask. The callback runs after the current synchronous execution finishes. Pending microtasks are then processed before the next task.
What is the output order of synchronous code, a promise callback, and a zero-delay timer?
Synchronous statements execute first because they are already on the current call stack. The promise reaction then runs during microtask processing. The timer callback runs afterward as a task. Therefore the typical order is synchronous output, promise output, then timer output.
Why are Promise callbacks called microtasks?
Promise reactions are placed into the runtime's microtask queue when they become ready to run. Microtasks are handled at a microtask checkpoint after the current JavaScript execution completes. The runtime drains the available microtasks before continuing with another task. This ordering gives promise-based continuations priority over ordinary task callbacks.
What happens if a microtask continuously creates more microtasks?
Each newly queued microtask can be processed during the same microtask-draining phase. If code keeps adding microtasks indefinitely, the runtime may be unable to reach the next task. That can delay timers and other event-loop work. This is why unbounded microtask chains can cause responsiveness problems.
How would you explain Promise jobs in an event-loop interview question?
I would separate the execution model into the current synchronous execution, microtask processing, and subsequent tasks. A promise settlement schedules its reactions rather than invoking them inline. Once the current execution completes, the runtime processes pending microtasks before advancing to another task. That ordering is why promise reactions commonly appear before timer callbacks, while long-running microtask chains can postpone later event-loop work.