【问题标题】:Chrome extension, javascript: Why is this firing twice?Chrome扩展,javascript:为什么会触发两次?
【发布时间】:2011-05-29 14:00:25
【问题描述】:

我的(测试)Chrome 扩展中有一段非常简单的代码:

    function test()
    {
    alert("In test!");
    }

   chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
    var url = tab.url;
        if (url !== undefined) {

        test();
    }
   });

我的问题是,为什么test() 会触发两次?更重要的是,如何让它只触发一次?

【问题讨论】:

  • 我的猜测是确实发生了 2 个选项卡更新,导致事件处理程序触发两次。
  • 我只有那一段代码...那么第二段来自哪里?
  • 请参阅我的回答,了解为什么您的代码看起来只会调用一次test(),但实际上它可以调用test() 任意次数。
  • 很好,罗伯。更准确地说是“任意次数”并回答第二次调用来自何处的问题:每个初始选项卡加载更新选项卡的状态为“加载”-> 调用 #1。当它完成加载时,它的状态将 updated 为“完成” -> 调用 #2。因此,对于每个 页面加载tab 对象 会更新两次。

标签: javascript google-chrome google-chrome-extension


【解决方案1】:

查看事件被调度时的不同状态。我认为,当状态“加载”或状态“完成”时,它会被分派一次。如果是这种情况,那么您的问题将通过以下方式解决:

 function test()
    {
    alert("In test!");
    }

   chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
    var url = tab.url;
        if (url !== undefined && changeinfo.status == "complete") {

        test();
    }
   });

【讨论】:

  • 不,确实如此...只是忘记重新加载扩展程序 :)) 需要等待 3 分钟才能接受您的回答...谢谢
  • 可悲的是,我和@Nikklas 有同样的问题,两次状态都是“完成”。 Wtf 铬?
  • 哦,很高兴我找到了这个页面。我想知道为什么它会触发两次。现在,很清楚了!
  • 为了澄清的目的,它会在有任何更新并且有不同类型的更新时触发。更新可以是 URL 更改、网站图标、状态等。因此您需要查看 changeinfo 对象以了解它是什么类型的更改。对我来说,我首先检查了 changeinfo 是否表示更新是“状态”更改,然后如果选项卡状态为“完成”if (changeinfo && changinfo.status && tab && tab.status == 'complete') 我在将所有参数打印到控制台后发现了这一点。
【解决方案2】:

我也对此感到困惑,并试图找到答案。只有经过一些实验,我才弄清楚为什么我会收到多个“完整”更新事件,因为我认为这是一个单页“更新”。

如果您的网页有 iframe,每个 iframe 都会触发“完成”事件并冒泡到父内容脚本。因此,如果有 iframe,更复杂的页面将触发大量 onUpdated 事件。

【讨论】:

  • 不,我的页面中没有 iframe。
  • 是的,这就是我的情况。它发生在复杂页面上,所以我收到了至少 7 个“完整”事件,现在我必须处理这个:)
【解决方案3】:

当你编写以下代码时:

chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
    var url = tab.url;
        if (url !== undefined) {

        test();
    }
});

您正在调用addListener 并告诉它调用test()不是立即,而是只要标签更新时。标签更新事件由 Chrome 浏览器本身广播,进而导致您的 test() 代码运行。

【讨论】:

    【解决方案4】:

    我知道这已经过时了,但无论如何......这也发生在我身上,也许这可以帮助某人。查看处理函数正在接收的 Tab 对象,我发现 favIconUrl 属性在两个调用中都不同,所以我想这与此有关,尽管我不知道这背后的原因.

    我认为这是一个错误,但经过深思熟虑和一些测试后,我放弃了错误理论。

    到目前为止,我所知道的是,如果更改了两个属性,则会触发两次事件,changeInfo 对象每次都包含一个属性。换句话说,如果改变的属性是 statusfavIconUrl,那么

    changeInfo = {status:"complete"};
    

    然后在下一次通话中

    changeInfo = {favIconuUrl : ".... whatever ..."};
    

    【讨论】:

      【解决方案5】:

      虽然我不确定为什么我们的代码会触发两次,但我遇到了类似的问题,这个答案对我有很大帮助。

      https://stackoverflow.com/a/49307437/15238857 Vaibhav 的回答非常聪明地以请求的详细信息对象的形式合并验证。 在记录详细信息对象时,我注意到原始触发的 frameId 为 0 的趋势,而第二次触发总是其他内容。因此,与其积极验证您是否正确提交了 URL,我更喜欢使用 if 语句在您有重复条目时返回并退出。 我在这里使用 onCompleted,但它也应该适用于 onUpdated。

      chrome.webNavigation.onCompleted.addListener(details => {
          //need to make sure that this only triggers once per navigation
          console.log(details);
          if (details.frameId !== 0) return;
      });
      

      【讨论】:

        【解决方案6】:

        我通过在更新时检查选项卡的标题解决了这个问题:

        chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
        
        var title = changeInfo.title;
            if (title !== undefined) {
               doSomething();
            }
        });
        

        【讨论】:

          【解决方案7】:

          两次是由于状态加载一次和状态完成一次。 如果您不关心状态,您也可以尝试 onCreated 事件。只会触发一次!

          【讨论】:

          • 如上所述,当状态为“完成”(多次完成)时,它可以触发不止一次。打印参数后,您可以看到它在更新由 favicon 触发时触发。因此,检查changeInfo 对象以查看它是否是“状态”更改,然后检查选项卡的状态是否为“完成”将确保您仅在页面加载完成时才能看到它。
          • 现在有了onCreated,它根本不会触发!
          猜你喜欢
          • 2013-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-08
          • 1970-01-01
          • 2011-01-27
          • 2021-07-08
          • 1970-01-01
          相关资源
          最近更新 更多