【问题标题】:Passing message from background.js to popup.js将消息从 background.js 传递到 popup.js
【发布时间】:2012-08-29 05:26:03
【问题描述】:

我正在尝试实现我自己的 chrome 扩展,在某个事件上,创建一个浏览器通知并使用在 background.js 中计算的数据填充弹出窗口

这是我的manifest.json 文件:

{
    "name": "Dummy name",
    "description": "Description",
    "manifest_version": 2,
    "version": "1.1.3",
    "icons": {
        "16": "icon_16.png",
        "48": "icon_48.png",
        "128": "icon_128.png",
        "256": "icon_256.png"
    },
    "browser_action": {
        "default_icon": "icon_48.png",
        "default_title": "Test",
        "default_popup": "popup.html"
    },
    "permissions": ["background","webRequest","webRequestBlocking","webNavigation","tabs","notifications"],
    "background": {
        "scripts":["jquery-1.8.1.min.js","classy.js","background.js"]
    }
}

我在background.js 中给sendMessage 打电话

show : function(result) {
    var that = this;
    chrome.extension.sendMessage({greeting: "hello"}, function(response) {
        console.log(response);
    });

    if(window.webkitNotifications) {
        var notification = webkitNotifications.createHTMLNotification('notification.html');
        notification.show();
        setTimeout(function(){
            notification.cancel();
            }, '7000');
        }
    }

我在popup.js 中的消息监听器(来自 chrome 扩展示例)

chrome.extension.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello")
      sendResponse({farewell: "goodbye"});
  });

我得到的唯一错误是

端口错误:无法建立连接。接收端不 存在。

感谢您的帮助!

【问题讨论】:

  • 后台页面加载很久才显示浏览器动作弹窗。显然,弹出脚本没有更改通过chrome.extension.onMessage绑定事件监听器。
  • 如前所述,这是基于事件触发的。由于事件发生在页面加载后的几秒钟内,是否仍然可以相信它没有被弹出窗口收听?
  • 确保你说的是真的。您可以输入一个alert('') 对话框来查看这些方法是否以预期的顺序出现。旁注,您可以通过chrome.extension.getBackgroundPage()(从弹出窗口访问后台的全局window对象)和chrome.extension.getViews({type:'popup'})[0](如果存在弹出窗口的全局window对象,从背景页面)。
  • 我刚刚对此进行了测试,实际上,弹出窗口中的任何操作都只能在它打开时触发。知道如何模拟消息发送吗?不幸的是,它与 getBackgroundPage() 和 getViews() 相同...仅在弹出窗口打开时起作用:(
  • “显然”也已被弃用,应避免使用。

标签: google-chrome google-chrome-extension messaging message-passing


【解决方案1】:

本地存储解决方案

由于弹出窗口没有持久状态,您可能希望使用 localStorage 存储弹出窗口状态并在弹出窗口打开时预加载它,并使用storage 事件来跟踪弹出窗口打开时状态的更改。

背景:

localStorage.setItem('popupData', JSON.stringify({ tabReady: true }));

弹出窗口:

// Load the state from localStorage when popup opens
let popupData = JSON.parse(localStorage.getItem('popupData'));

// Keep track of changes to the popup state while the popup is open
window.addEventListener('storage', (e) => {
  if (e.key === 'popupData') {
    popupData = JSON.parse(e.newValue);
    console.log(popupData.tabReady);
  } 
});

【讨论】:

    【解决方案2】:

    这是我发现的将数据从 background.js 发送到 popup.js 的两种最简单的方法:

    1) 使用存储

    将值保存到存储中,一旦弹出窗口打开,它会从存储中获取值并将它们显示在弹出窗口中。

    background.js

    chrome.storage.sync.set({ 'dataValue1': 'Some data 1.' });
    chrome.storage.sync.set({ 'dataValue2': 'Some data 2.' });
    

    popup.js

    function updatePopup() {
        chrome.storage.sync.get(['dataValue1', 'dataValue2'], function (data) {
            document.getElementById("popupElement1").innerText = data.dataValue1;
            document.getElementById("popupElement2").innerText = data.dataValue2;
        });
    }    
    document.addEventListener('DOMContentLoaded', updatePopup);
    

    popup.html

    <html>    
    <head>
        <script src="popup.js"></script>
    </head>    
    <body>
        <p id="popupElement1"></p>
        <p id="popupElement2"></p>
    </body>    
    </html>
    

    ma​​nifest.json

    {
        "name": "Background2popup",
        "version": "1.0",
        "manifest_version": 2,
        "description": "This is a demo",
        "browser_action": {
            "default_popup": "popup.html"
        },
        "background": {
            "scripts": [
                "background.js"
            ]
        },
        "permissions": [
            "<all_urls>",
            "storage",
            "tabs"
        ]
    }
    

    2) 使用 chrome.runtime.sendMessage()

    一旦弹出窗口打开,您会从弹出窗口向后台发送消息以建立连接/握手(否则,您将收到“未检查的 runtime.lastError:无法建立连接。接收端不存在。”如果您尝试从后台发送消息到弹出窗口并且弹出窗口未打开)。建立连接后,您首先使用后台的 sendResponse 将要发送的数据发送到弹出窗口。

    background.js

    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
        if (request.method == "getStatus") {
            console.log(request.data)
            sendResponse({ method: "peepee", data: "poopoo" })
        }
    });
    

    popup.js

    chrome.runtime.sendMessage({ method: "getStatus", data: "xxx" }, function (res) {
        document.getElementById("popupElement1").innerText = res.method;
        document.getElementById("popupElement2").innerText = res.data;
    return true;
    });
    

    popup.html & manifest.json 与第一个示例相同

    【讨论】:

      【解决方案3】:

      弹出窗口没有标签 ID,因此您会收到错误消息。

      在这种情况下,您可以使用chrome.runtime.sendMessagechrome.runtime.onMessage.addListener

      所以在 background.js

      chrome.runtime.sendMessage({
          msg: "something_completed", 
          data: {
              subject: "Loading",
              content: "Just completed!"
          }
      });
      

      而在 popup.js

      chrome.runtime.onMessage.addListener(
          function(request, sender, sendResponse) {
              if (request.msg === "something_completed") {
                  //  To do something
                  console.log(request.data.subject)
                  console.log(request.data.content)
              }
          }
      );
      

      希望对你有帮助。

      谢谢,

      【讨论】:

      • 如果我打开了多个选项卡并向 popup.js 发送消息怎么办。哪个 popup.js 会收到它?如何将消息发送到我想发送消息的地方@Perfect
      • 您应该将消息从弹出窗口发送到后端脚本。此时,您可以在后端脚本中获取 tab_id 来识别哪个选项卡的弹出窗口发送到后台。无法将消息从后端脚本发送到弹出窗口,但您可以将后端脚本发送到特定选项卡的内容脚本。或者您可以在后端和弹出窗口之间创建连接。看看这个链接。 stackoverflow.com/questions/13546778/…
      • 我在看到这个之前使用 tabid 做了完全相同的事情。感谢@Perfect 提供另一种方式
      【解决方案4】:

      要解决这个问题,您需要先向 background.js 发送握手消息,然后将实际数据从 background.js 发送到 popup.js 例如:就我而言,我所做的是

      popup.js

      chrome.runtime.sendMessage({data:"Handshake"},function(response){
      	
      			});
      chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
      	str = JSON.stringify(message.data);
      });

      background.js

      chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
      //alert(message.data);
      	chrome.runtime.sendMessage({data:datax},function(response){
      			});
      			});

      我试图做的是,只要我们点击图标,握手消息就会发送到 background.js,当它收到它时,我们可以发送变量或我们想要发送的任何数据到 popup.js在 popup.html 上呈现它。

      【讨论】:

      • 我喜欢握手的想法,它确保弹出窗口是活动的(没有被破坏)并且能够监听传入的数据。此外,这似乎是每个页面加载的一次性事件,它遵循 API 的 Simple one-time request methods
      • 但这意味着调用是由Popup发起的。我相信 OP 想要从背景到弹出的对话启动。如果弹出窗口想从后台提取数据,它也可以执行以下标准方法: let bg= chrome.runtime.getBackgroundPage() 然后通过 console.log(bg.message) 获取 msg;这里的“消息”是 background.js 文件中的一个对象
      【解决方案5】:

      使用runtime.sendMessage 将消息发送到后台脚本,使用tabs.sendMessage 从后台发送到内容脚本。

      请注意,您需要指定标签ID:

      chrome.tabs.query({ active: true }, (tabs) => {
          chrome.tabs.sendMessage(tabs[0].id, { greeting: 'hello' }, (response) => {
              console.log(response);
          });
      });
      

      您可以在此处找到完整的示例和文档:https://developer.chrome.com/extensions/messaging#simple

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多