Advanced 12 min

Watching the DOM with MutationObserver

For single-page apps and late-hydrating components: stop polling, start observing.

setInterval is the apprentice's tool. It runs whether the page has changed or not, burns battery on mobile, and races against itself when the target arrives late.

MutationObserver is the witch's tool. It watches a subtree silently and fires only when something actually changes. You attach it to a stable ancestor, set childList and subtree to true, and disconnect the observer the moment your target is found. The browser does the work; you do not.

A common pattern: wrap MutationObserver in a waitForElement helper that returns a promise. Your variant code then awaits the element before mutating, with no global state and no leaked observers.

Example

function waitForElement(selector, root = document.body) {
  return new Promise((resolve) => {
    const found = root.querySelector(selector);
    if (found) return resolve(found);
    const obs = new MutationObserver(() => {
      const el = root.querySelector(selector);
      if (el) { obs.disconnect(); resolve(el); }
    });
    obs.observe(root, { childList: true, subtree: true });
  });
}

Try this on the Shop

The best way to learn is to ship. Open this surface and apply the lesson.

Hold the MutationObserver Orb