MutationObserver 太慢,无法在动态 iframe 中重新定义 navigator 属性?

问题描述 投票:0回答:1

我正在对 Chrome 扩展进行一些更新,重新定义 navigator.userAgent, 我在用 MutationObserver 替换 DOMNodeInserted 时遇到了这种行为..

这个问题是通用的,不需要通过 Chrome 扩展进行测试。

解释此行为的最佳方法是导航至: https://webbrowsertools.com/useragent/

然后...使用控制台运行以下 javacript 代码,并检查 iframe> navigator.userAgent 的响应:

DOMNodeInserted 工作正常,iframe > navigator.userAgent 已切换:

document.addEventListener('DOMNodeInserted', function(event)
{
    if (event.target.tagName == 'IFRAME')
        for (var i=0; i<window.frames.length; i++)
            try { Object.defineProperty(window.frames[i].navigator, 'userAgent', {value:'TEST'}); } catch(e) {}
});

MutationObserver 不起作用,iframe > navigator.userAgent 未切换:

var observer = new MutationObserver(function(mutations)
{
    for (var mutation of mutations)
        for (var item of mutation.addedNodes)
            if (item.tagName == 'IFRAME')
                for (var i=0; i<window.frames.length; i++)
                    try { Object.defineProperty(window.frames[i].navigator, 'userAgent', {value:'TEST'}); } catch(e) {}
});
observer.observe(document, { childList:true, subtree:true });

请原谅通过 window.frames 进行的粗略迭代,而不是实际的 event.target

我相信这与 MutationObserver 太慢有关,但我不知道如何解决这个问题?!

javascript navigator mutation-observers
1个回答
0
投票

我无法重现您的行为,所以代码片段抱怨 CORS iframe,所以这里是一个 JSFiddle

这是代码

const daFrame = document.createElement("iframe"),
      body = document.body,
      obs = new MutationObserver(function(muts){
        muts.forEach(mut => {
          if(mut.type !== "childList"){return}
          mut.addedNodes.forEach(n => {
            if(!(n instanceof HTMLIFrameElement)){return}
            Object.defineProperty(
              n.contentWindow.navigator,
              "userAgent",
              {value: "whateva"}
            )
          })
        })
      });

obs.observe(document.body, {childList: true, subtree: true});

setTimeout(() => document.body.appendChild(daFrame), 0);

setTimeout(() => console.log(`userAgent =`, window.frames[0].navigator.userAgent), 3000);

我使用

setTimeout
引入延迟来启动
MutationObserver
,以防 DOM 节点(在本例中为 iframe)可能在观察者启动之前插入。

如果您不想使用 setTimeout,您还可以将

Promise
推送到外部数组并解析这些推送的承诺。但这不是这个问题的主题。

© www.soinside.com 2019 - 2024. All rights reserved.