是什么可能导致整个文档上的突变观察者,而子树则在孩子添加时不发射?

发布于 2025-02-04 15:29:23 字数 2645 浏览 3 评论 0原文

有时,突变观察者回调不会在我期望的时候发射。

如果我在开发人员工具控制台中运行此代码:

// callback for mutations observer
 callbackForAllChanges = function (mutationsList, observer) {
  console.log("mutations: ", mutationsList);
};

// create mutation observer
 allChanges = new MutationObserver(callbackForAllChanges);


// attach mutation observer to document
  allChanges.observe(document, {
    childList: true,
      subtree:true
  });

// create new child
document.body.appendChild(document.createElement("div"));

我希望当我创建新孩子时,回调会发射。但是有时确实如此,有时却没有。

当我在stackoverflow上运行DevTools控制台中的代码时,它可以正常工作:我看到突变:[mutationRecord]已记录到控制台。

当我继续 Twitter 并在DevTools控制台中运行上述代码,它似乎不起作用:<代码突变:[突变记录]未记录到控制台。

是什么可能导致突变观察者在Twitter上不起作用?

要重新创建问题,

  1. 请访问 twitter
  2. 打开DevTools console
  3. 粘贴以上代码,并参见突变:[mutationRecord] /code>不记录

更新2

Now it works for me on twitter so seems intermittent.

更新2

It's stopped working again on twitter. I also found if I add a mutation observer to a div I create, that also doesn't work but works on other sites.
const newDiv = document.createElement('div')
newDiv.setAttribute('id','newDiv')
// callback for mutations observer
 callbackForAllChanges = function (mutationsList, observer) {
  console.log("mutations: ", mutationsList);
};

// create mutation observer
 allChanges = new MutationObserver(callbackForAllChanges);


// attach mutation observer to document
  allChanges.observe(newDiv, {
    childList: true,
      subtree:true
  });

// create new child
newDiv.appendChild(document.createElement("div"));

更新3

  • 突变观察者尚未停止在隐身方面工作,而
  • 在不工作时,请关闭所有扩展名 nove 均未解决突变观察者,
  • 并且重新启动Chrome似乎 修复突变观察者停止工作时,
  • 清除cookie 修复了问题

更新4个

It may be related to an infinite loop where when a mutation is observed, a node is added. This causes a mutation to be observed (the new added node). And so on...

示例,

  const callbackForAllChanges = function (mutationsList, observer) {
    if (mutationsList.find((record) => record.type === "childList")) {      
  document.body.appendChild(document.createElement("div"));
    }
  };

我认为如果发生这种情况,它可能会触发突变工作以停止工作。

Sometimes the mutation observer callback doesn't fire when I expect it to.

If I run this code in developer tools console:

// callback for mutations observer
 callbackForAllChanges = function (mutationsList, observer) {
  console.log("mutations: ", mutationsList);
};

// create mutation observer
 allChanges = new MutationObserver(callbackForAllChanges);


// attach mutation observer to document
  allChanges.observe(document, {
    childList: true,
      subtree:true
  });

// create new child
document.body.appendChild(document.createElement("div"));

I would expect callback to fire when I create a new child. But sometimes it does and sometimes it doesn't.

When I run the code in the devtools console while on stackoverflow it works: I see mutations: [MutationRecord] logged to the console.

When I go on twitter and run the above code in the devtools console, it doesn't seem to work: mutations: [MutationRecord] is not logged to the console.

What could cause Mutation Observer to not work on twitter?

To recreate issue

  1. Go to twitter
  2. Open the devtools console
  3. Paste the above code and see mutations: [MutationRecord] does not log

UPDATE

Now it works for me on twitter so seems intermittent.

UPDATE 2

It's stopped working again on twitter. I also found if I add a mutation observer to a div I create, that also doesn't work but works on other sites.

const newDiv = document.createElement('div')
newDiv.setAttribute('id','newDiv')
// callback for mutations observer
 callbackForAllChanges = function (mutationsList, observer) {
  console.log("mutations: ", mutationsList);
};

// create mutation observer
 allChanges = new MutationObserver(callbackForAllChanges);


// attach mutation observer to document
  allChanges.observe(newDiv, {
    childList: true,
      subtree:true
  });

// create new child
newDiv.appendChild(document.createElement("div"));

UPDATE 3

  • Mutation observer hasn't stopped working in incognito
  • Turning all extension off doesn't fix mutation observer when it's not working
  • Quitting and restarting chrome seems to fix Mutation observer when it stops working
  • Clearing cookies does not fix the issue

UPDATE 4

It may be related to an infinite loop where when a mutation is observed, a node is added. This causes a mutation to be observed (the new added node). And so on...

Example

  const callbackForAllChanges = function (mutationsList, observer) {
    if (mutationsList.find((record) => record.type === "childList")) {      
  document.body.appendChild(document.createElement("div"));
    }
  };

I think if this happens it might trigger the mutation work to stop working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

刘备忘录 2025-02-11 15:29:24

我面临同样的问题,现在我通过使用循环并检查是否手动进行了一些更改来修补回调。

setInterval(() => {
  const recs = allChanges.takeRecords()
  if (recs.length === ) return
  yourcallback(recs)
}, 30)

I am facing the same problem, for now I patched the callback by using a loop and checking if some changes were made manually.

setInterval(() => {
  const recs = allChanges.takeRecords()
  if (recs.length === ) return
  yourcallback(recs)
}, 30)

或十年 2025-02-11 15:29:24

我能够在以下特定情况下重现此操作:

  1. 开发工具是打开
  2. 在MutationObserver回调
  3. 加载页面中首次
  4. 代码, 具有断点或调试器语句Breakpoint
  5. MutationObserver回调再也不会为任何未来的页面重新加载
  6. 重新加载到网站并启动新标签(即创建新页面过程)将状态重置回到第一步的

其他轶事:

  • 我尝试使用一些尝试此词 :较旧的铬(大约V97)的建筑物,有趣的是,如果试图从突变观察者回调断点中重新加载页面,其中许多人会崩溃。
  • 存储对突变处理器的引用并使用takeRecord()按预期工作。如上,它充满了突变记录。
  • 使用QueuemicRotask(&lt; cb&gt;)将您的工作与突变观察者回调中的工作解矛并不能解决问题。
  • 使用settimout(&lt; cb&gt; 0)确实解决了问题。

因此,如果您遇到与我相同的问题,解决方法是将您的突变观察者回调在settimeout()中,如下所示...

new MutationObserver(() => setTimeout(myHandler, 0));

我不愿意将其称为答案说实话。我相信这里有一个铬的heis虫。如果您从未打开开发工具,那么这种解决方法是多余的。

I'm able to reproduce this with these specific circumstances:

  1. Dev Tools are open
  2. Code has breakpoint or debugger statement inside MutationObserver callback
  3. Load page first time and the page stops on the breakpoint successfully
  4. Reload the page while still in the breakpoint
  5. MutationObserver callback never runs again for any future page reloads
  6. Closing the page and any others to the site and starting a new tab (ie. create new page process) resets the state back to the first step

Other anecdotes:

  • I tried this with some older builds of chromium (circa v97) and interestingly I found that many of them would crash if trying to reload the page from a mutation observer callback breakpoint.
  • Storing a reference to the MutationObserver and using takeRecord() works as expected. As in, it was full of mutation records.
  • Using queueMicrotask(<cb>) to decouple your work from the mutation observer callback does NOT resolve the issue.
  • Using setTimout(<cb>, 0) DOES resolve the issue.

So if you're experience the same issue that I am, the workaround will be to wrap your mutation observer callback in a setTimeout() as follows...

new MutationObserver(() => setTimeout(myHandler, 0));

I don't feel comfortable calling this an answer to be honest. I believe there is a heisen-bug in Chromium here. If you never open Dev Tools this workaround is superfluous.

最近可好 2025-02-11 15:29:24

此答案在

我想避免重构很多代码,因此我想出了这个hacky的解决方案,以将本机MutationObserver类包装在您自己的匿名类中(需要在之前运行任何被实例化的观察者):

function fixObserver(name) {
  let original=window[name];
  window[name]=class {
    constructor (cb) {
      return new original((...params) => { 
        setTimeout(() => cb(...params));
      });
    }
  };
}
fixObserver('MutationObserver');
fixObserver('ResizeObserver');
fixObserver('IntersectionObserver');

This answer dovetails on the response from mayfield which is excellent. I agree that this is a Chromium Devtools bug, reproducible with the steps that he mentioned in his answer. setTimeout() seems to work (albeit inconsistently) to mitigate this. I wonder if this bug might also impact other observers as well ...

I wanted to avoid refactoring a lot of code so I came up with this hacky solution to wrap the native MutationObserver class in your own anonymous class (needs to be run prior to any observers being instantiated):

function fixObserver(name) {
  let original=window[name];
  window[name]=class {
    constructor (cb) {
      return new original((...params) => { 
        setTimeout(() => cb(...params));
      });
    }
  };
}
fixObserver('MutationObserver');
fixObserver('ResizeObserver');
fixObserver('IntersectionObserver');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文