Google chrome extension 消息传递不起作用

Google chrome extension 消息传递不起作用,google-chrome-extension,Google Chrome Extension,bacground.js chrome.tabs.create({url: "http://www.google.com", "active":true}, function(tab) { console.log(tab.id);// 315 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { console.log(response.farewell); }); }); contentscript

bacground.js

chrome.tabs.create({url: "http://www.google.com", "active":true}, function(tab) {
console.log(tab.id);// 315
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
contentscript.js

chrome.runtime.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"});
  });
});
日志:


如何修复它?

发生此错误的原因似乎是,在后台脚本发送消息时,内容脚本尚未注入页面。因此,“接收端不存在”

我假设(因为我没有超过50名代表能够对您的问题发表评论并首先澄清这一点,所以如果我错了,请纠正我)在manifest.json文件中,您以以下方式指定它:

"content_scripts": [{
    "matches": ["*://xyz.com/*"],
    "js": ["contentscript.js"]
}]
如果这确实是注入内容脚本的方式,那么您需要知道内容脚本只有在DOM完成渲染后才会被注入。(在以下链接上搜索“run_at:”)这意味着当您从后台脚本发送该消息时,内容脚本仍在“加载”

好消息是,您可以通过向manifest.json文件中的content_scripts参数添加第三个键值对来指定加载内容脚本的时间,如下所示:

"content_scripts": [{
    "matches": ["*://xyz.com/*"],
    "js": ["contentscript.js"],
    "run_at": "document_start"
}]
这会告诉扩展,您希望在构建DOM或运行任何其他脚本之前(即尽早)注入contentscript.js

如果上述技术仍然给您带来相同的错误,这表明即使是文档启动也不够早。在这种情况下,让我们完全考虑另一种方法。您目前正在尝试将后台脚本连接到内容脚本。当内容脚本成功注入页面时,为什么不将其连接到后台脚本?后台页面始终处于运行状态,因此保证能够从内容脚本接收消息,而不会抱怨“接收端不存在”。以下是您的操作方法:

在background.js中:

chrome.runtime.onConnect.addListener(function(port) {
    console.log("background: received connection request from 
                 content script on port " + port);
    port.onMessage.addListener(function(msg) {
        console.log("background: received message '" + msg.action + "'");
        switch (msg.action) {
            case 'init':
                console.log("background script received init request 
                             from content script");
                port.postMessage({action: msg.action});
                break;
        }
    });
});
在contentscript.js中:

var port_to_bg = chrome.runtime.connect({name: "content_to_bg"});
port_to_bg.postMessage({action: 'init'});
port_to_bg.onMessage.addListener(function(msg) {
    switch (msg.action) {
        case 'init':
            console.log("connection established with background page!");
            break;
    }
}

请随时提出更多问题进行澄清!我很想知道第一种方法是否有效。如果没有,第二种方法肯定会成功。

您的方法:内容脚本连接到backround。是 啊因此,您可以使用
chrome.runtime.sendMessage
。但是我需要-将消息从后台发送到内容脚本。是的,一旦内容脚本连接到后台页面,所有的后续通信都通过端口进行(双方都可以访问端口)。在manifest.json中添加“run_at”:“document_start”的第一种方法对您有效吗?
var port_to_bg = chrome.runtime.connect({name: "content_to_bg"});
port_to_bg.postMessage({action: 'init'});
port_to_bg.onMessage.addListener(function(msg) {
    switch (msg.action) {
        case 'init':
            console.log("connection established with background page!");
            break;
    }
}