【问题标题】:Chrome extension message listener fires twiceChrome 扩展消息监听器触发两次
【发布时间】:2020-09-12 14:24:28
【问题描述】:

我正在开发 Chrome 扩展程序。我尝试学习内容和背景之间的消息传递。我为此开发了简单的项目。但我有问题。

基本思路是

  • 扩展弹出窗口上的用户单击按钮
  • 一个函数(bot.js)从标签的内容中查找图片然后扩展(background.js)会下载它。

问题是 background.js 中的 port.onMessage.addListener() 触发了两次。

background.js 向 contentscript.js 发送消息时,控制台中有两条相同的消息,或者当我尝试在 background.js 中下载(代码行“Do Something”)时,它会下载文件两次。

我该如何解决这个问题?

popup.html

<!doctype html>
<html>
  <head>
    <title>Test Plugin</title> 
    <script src="background.js"></script>
    <script src="popup.js"></script>
  </head>
  <body>
    <h1>Test Plugin</h1>
    <button id="btnStart">Button</button>
  </body>
</html>

popup.js

document.addEventListener('DOMContentLoaded', function() {
    var checkPageButton = document.getElementById('btnStart');
    checkPageButton.addEventListener('click', function() {  
      GetImages("Some URL");
    }, false);
  }, false);


  var tab_title = '';
  function GetImages(pageURL){
    // Tab match for pageURL and return index
    chrome.tabs.query({}, function(tabs) {
      var tab=null;      
      for(var i=0;i<tabs.length;i++){
        if(tabs[i].url==undefined || tabs[i].url=="" || tabs[i]==null){}
        else{
          if(tabs[i].url.includes(pageURL)){
            tab=tabs[i];
            break;
          }
        } 
      }
      
      if(tab!=null){
          chrome.tabs.executeScript(tab.id, {
            file: "bot.js"
          }, function(results){
            console.log(results);
          });
      }
    });
  }

bot.js

var thumbImagesCount = document.querySelectorAll('.classifiedDetailThumbList .thmbImg').length;
var megaImageURL=document.querySelectorAll('.mega-photo-img img')[0].src;
console.log(megaImageURL + " from bot.js");
port.postMessage({key:"download", text: megaImageURL});

background.js

chrome.runtime.onConnect.addListener(function (port) {
    console.assert(port.name == "content-script");
    port.onMessage.addListener(function(message) {
        
        console.log(message);
        if(message.key=="download"){
            // Do Something
            // Event fires twice
            port.postMessage({key:"download", text: "OK"});
        }
    })
});

contentscript.js

console.log("content script loaded!");
var port = chrome.runtime.connect({name: "content-script"});
port.onMessage.addListener(function(message){
    console.log(message);
});

ma​​nifest.json

{
    "manifest_version": 2,
  
    "name": "Test Extension",
    "description": "This extension will download images from gallery",
    "version": "1.0",
    "icons": { 
        "16": "bot16.png",
        "48": "bot48.png",
       "128": "bot128.png" },
    "browser_action": {
        "default_icon": "bot48.png",
        "default_popup": "popup.html"
    },
    "permissions": [
        "activeTab",
        "downloads",
        "http://*/",
        "https://*/"
    ],
    "background": {
        "persistent": false,
        "scripts": ["background.js"]
    },
    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["contentscript.js"]
        }
    ]
  }

【问题讨论】:

  • manifest.json 中声明的后台脚本已经有自己的页面,一个隐藏的后台页面运行,所以你不应该在弹出窗口中加载它,因为它没有任何意义。在这种情况下,它还会创建第二个侦听器。另见Accessing console and devtools of extension's background.js
  • 感谢您的回答。它解决了我的问题。
  • @wOxxOm 看起来我们有一个经典示例,说明为什么不在 cmets 中发布答案或部分答案 - OP 的问题已解决,但问题仍显示为未回答,没有人可以投票,改进,或接受您的解决方案。 :(
  • @IMSoP,问题是,扩展程序有很多活动部件,有时在没有确认猜测正确的情况下发布答案是浪费。
  • @wOxxOm 是的,该平台不适合那种事情,但理想的做法是让 cmets 保留澄清的问题,并将猜测作为答案发布,如果澄清使它们过时,可以随时删除.

标签: javascript google-chrome-extension


【解决方案1】:

manifest.json 中声明的后台脚本已经有它自己的页面,一个隐藏的后台页面运行,所以你不应该在弹出窗口中加载它,因为如果有 API 事件的侦听器没有意义,后台页面已经在听他们了。在这种情况下,副本还会在弹出窗口打开时创建第二个侦听器。

解决方案:不要在弹窗中加载 background.js。

另见Accessing console and devtools of extension's background.js

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多