MutationObserver Scheduling
MutationObserver callbacks are delivered through the microtask mechanism after relevant DOM mutations. They run after the current JavaScript execution completes and before the event loop proceeds to a later task such as a timer or user-input event.
A `MutationObserver` watches selected DOM changes and queues its observer callback when matching mutations occur. The callback does not execute synchronously at the exact statement that changes the DOM; delivery is deferred until the appropriate microtask checkpoint.
Multiple mutations can be collected before delivery. A single observer callback can therefore receive several `MutationRecord` objects through its records array, allowing related changes to be processed together rather than invoking the callback separately for every mutation.
The important event-loop ordering is that ordinary synchronous JavaScript finishes first. Then pending microtasks, including MutationObserver notification work, are processed before the browser moves on to a later task such as a `setTimeout` callback. This ordering is useful when reasoning about DOM state observed by other asynchronous code.
MutationObserver scheduling is distinct from `setTimeout(..., 0)`: a zero-delay timer schedules a task, whereas MutationObserver delivery participates in the microtask checkpoint. Promise reactions also use the microtask mechanism, so their relative ordering can matter when both promises and DOM mutations are involved.
Observers can be controlled with `observe()`, `disconnect()`, and `takeRecords()`. `disconnect()` stops future observation, while `takeRecords()` retrieves records that have already been queued for that observer without waiting for the normal callback delivery.
Key points
- MutationObserver delivery occurs through the microtask mechanism.
- Callbacks are deferred until the current JavaScript stack has finished.
- Several DOM mutations may be delivered together as multiple `MutationRecord` objects.
- MutationObserver delivery happens before the event loop advances to a later task.
- Promise reactions and MutationObserver delivery both participate in microtask processing, so ordering can matter.
Interview questions
What is the difference between disconnect() and takeRecords()?
`disconnect()` stops the observer from receiving further mutations. It does not mean the same thing as consuming the observer's pending records. `takeRecords()` returns records that have already been queued for that observer, allowing code to retrieve them explicitly instead of waiting for normal callback delivery.
When does a MutationObserver callback run relative to synchronous JavaScript and a zero-delay timer?
The DOM mutation itself happens synchronously, but the observer callback is deferred. The callback is delivered during microtask processing after the current JavaScript execution has completed. A `setTimeout(..., 0)` callback is a later task, so it normally runs after the observer notification has been processed.
Why might one MutationObserver callback contain several MutationRecord objects?
MutationObserver is designed to collect matching DOM changes for delivery rather than requiring immediate callback execution for every individual mutation. If several relevant mutations occur before notification is delivered, their records can be passed together in the callback's records array. This batching reduces unnecessary callback invocations and lets code process a group of related changes.
How does MutationObserver scheduling interact with Promise callbacks?
Promise reactions and MutationObserver notification both participate in microtask processing. The exact observable ordering depends on when each piece of work is queued and on the event-loop checkpoint semantics, so code should not casually treat all asynchronous callbacks as equivalent. In an interview, the important distinction is that neither should be modeled as an ordinary timer task.
Why is MutationObserver preferable to polling for many DOM-change detection tasks?
MutationObserver lets the platform notify code when matching DOM mutations occur, avoiding repeated checks on a timer. Its callback receives structured mutation records, so the code can inspect what changed rather than repeatedly comparing the entire DOM. Scheduling through microtask processing also provides prompt notification after synchronous DOM work without turning the observer into a timer task.