Javascript 何时触发MutationObserver回调?

Javascript 何时触发MutationObserver回调?,javascript,dom,browser,dom4,Javascript,Dom,Browser,Dom4,我知道MutationObserver回调可能在DOM更改后的某个时候被调用。但问题是:这些回调的时机是什么? 回调是否进入浏览器的事件队列?如果是,他们什么时候进入队列 这些回调是: DOM突变发生后立即调用 操作DOM的函数完成后立即调用 调用堆栈为空时立即调用 DOM突变发生后立即排队 操作DOM的函数完成后立即排队,或 改天吧 例如,如果执行以下代码段(使用): “MutationObserver”应该在“消息事件”之前还是之后打印? 还是定义了实现 我在Chromium26上的“消

我知道MutationObserver回调可能在DOM更改后的某个时候被调用。但问题是:这些回调的时机是什么? 回调是否进入浏览器的事件队列?如果是,他们什么时候进入队列

这些回调是:

  • DOM突变发生后立即调用
  • 操作DOM的函数完成后立即调用
  • 调用堆栈为空时立即调用
  • DOM突变发生后立即排队
  • 操作DOM的函数完成后立即排队,或
  • 改天吧
例如,如果执行以下代码段(使用):

“MutationObserver”应该在“消息事件”之前还是之后打印? 还是定义了实现

我在Chromium26上的“消息事件”之前得到了“MutationObserver”,尽管DOM变异是在消息发布之后。这可能表明MutationObserver回调是而不是使用事件队列

我在谷歌上搜索了HTML规范、DOM规范或浏览器实现文档,但没有找到任何与此行为相关的内容


有关MutationObserver回调时间的任何解释或文档,请?

MutationObserver是异步启动的,但“很快”,这意味着它们在队列中的其他事件(如布局、绘制或触发事件)之前启动

这改善了同步性的丧失,因为在你的观察者有机会做出反应之前,你不必担心屏幕闪烁或其他不好的事情发生


在开发者笔记中,他们谈到了“微任务结束”的计时模型。我同意这是一个缺乏文档的问题。

我将在两年后根据报告回答我自己的问题

如规范所示:

要对复合微任务排队,请运行以下步骤:

  • 如果设置了“变异观察者复合微任务队列”标志,则终止这些步骤
  • 设置变异观察者复合微任务队列标志
  • 将复合微任务排队以通知突变观察者
  • 而“将复合微任务排队”链接到解释微任务队列模型

    因此,我们可以得出这样的结论:
    MutationObserver
    回调是作为微任务启动的,这确实比前面提到的任务队列任务要快

    为了进一步了解事件循环和处理模型,HTML规范将是完美的


    就我个人而言,我很高兴看到
    MutationObserver
    s是标准的一部分,并且有一个记录良好且一致的计时模型。有了
    MutationObserver
    s,我认为它们现在已经可以用于生产了。

    我的猜测是,如果突变观察者使用事件队列,
    message event
    出现在
    MutationObserver
    之前,这完全不足为奇。
    setZeroTimeout
    中的
    postMessage
    处理程序触发一个事件(添加到事件队列),然后
    setAttribute
    调用触发观察者(这可能还会在消息事件后面向队列添加一个事件)。@apsillers我在“message event”之前得到“MutationObserver”,不是相反。啊,我错了。然后,是的,这似乎表明
    MutationObserver
    s不使用事件队列。这可能会因为
    postMessage
    事件的行为可能与其他事件不同而进一步复杂化,但我不是100%肯定。@apsillers您是否建议在这个问题中使用其他异步事件进行测试?谢谢您的详细解释!我认为我应该等到模型被修复并记录下来,然后再根据回调顺序的假设编写任何东西;我使用MutationObserver来检测Angular SPA应用程序中的更改,问题是每个用户导航都会多次触发这些回调。我想知道是否有一种方法可以检测何时完成,也就是说,当DOM最终加载/更改时,除非用户再次导航,否则不会再发生任何更改。@david您不能确定不会再发生任何更改,因为这些监视程序可以继续启动,并且在
    $timeout
    等方面可能会有更多的更改。然而,我认为假设只要没有挂起的AJAX请求,并且DOM在一两秒钟内没有更新,DOM就不再被更改,这是非常安全的。
    var target = document.body;
    
    new MutationObserver(function(mutations) {
      console.log('MutationObserver');
    }).observe(target, {
      attributes: true,
      childList: true,
      characterData: true
    });
    
    
    // Post message
    setZeroTimeout(function () { console.log('message event'); });
    // DOM mutation
    target.setAttribute("data-test", "value");