mutationobserver 回调作为微任务执行,紧接同步脚本结束后、下一次宏任务前运行,批量合并变更、与 promise 微任务同级但按注册顺序执行,错误不中断后续观察,disconnect 可清空待处理回调并支持复用实例。

MutationObserver 的回调是作为微任务(microtask)插入执行队列的,它不打断当前同步代码,也不等同于 setTimeout 或 requestIdleCallback 这类宏任务,而是紧接在当前同步脚本结束后、下一次宏任务开始前执行。
回调触发时机很明确
只要一次 JS 执行栈清空,浏览器就会检查微任务队列:如果 MutationObserver 有已排队但未处理的变更,就批量合并后推入微任务队列,并在本轮微任务阶段统一执行回调。
- 连续多次 DOM 修改(比如循环添加 5 个节点),只触发一次回调,mutations 数组里包含全部 5 条记录
- 回调一定晚于同步语句(如 console.log、赋值、appendChild),但早于 Promise.then() 后续链中排在它后面的微任务
- 它和 Promise.resolve().then() 属于同一微任务层级,谁先注册谁先执行;但 MutationObserver 回调本身不会被 Promise 链“包裹”,是独立入队的
和 Promise 微任务共存时的顺序
假设同步代码中同时触发了 Promise.then 和 DOM 变更,执行顺序取决于注册时机:
- 先调用 Promise.resolve().then(...) → 该微任务先入队
- 再执行 document.body.appendChild(...) → 触发 MutationObserver,回调微任务后入队
- 结果:Promise.then 先执行,MutationObserver 回调后执行
- 但如果 DOM 变更发生在 Promise.then 回调内部,则 MutationObserver 回调会排在该 Promise 微任务之后的下一个微任务位置
异常不会中断后续观察
回调里抛出未捕获错误,只会终止本次回调执行,不影响 MutationObserver 继续监听和下一次触发:
- 错误不会传播到外部,也不会导致 observer 自动停止
- 后续 DOM 变更仍会照常收集、合并、入队并执行新回调
- 建议在回调内加 try/catch 包裹关键逻辑,避免静默失败影响业务流程
主动控制衔接点:disconnect 和 observe 可重置链条
调用 disconnect() 会清空待处理的微任务(即已排队但尚未执行的回调),后续再 observe() 就开启新的观察周期:
- 适用于需要“暂停响应→做清理→再恢复”的场景,比如画布编辑中途切换模式
- 注意:disconnect 后立即发生的 DOM 变更不会被记录,直到重新 observe 才开始捕获
- 可复用同一个 observer 实例观察不同节点,只需反复调用 observe() 并传入新 target 和配置











