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

我正在开发一个 Chrome 的扩展程序,出现了一个问题,在我的 inject.js中,我提出了这样一个请求:

chrome.extension.sendRequest({command:'skip'},callback)

在我的 backound.js 中,我只需要添加一个 request Listener,比如:

chrome.extension.onrequest.addListener(function(req,sender,res){console.log("procession"})

但有一个错误:

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

看起来像是铬合金的窃听器? 附注:
我宣言的一部分 Json

"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["< all_urls >"],
"js": ["inject.js"]
}
],

我在 Chromium 17中,我试着重新加载扩展,重新打开浏览器... 什么都没发生
有人有主意了吗?

129648 次浏览

我发现自己遇到了和你描述的一样的问题。我发现对我有用的解决方案是使用背景页面而不是背景脚本,如下所示:

"background_page": "src/background.html",
// maybe this seems to work instead of background { scripts [] }


/* this gives a Port error: Could not ...
"background": {
"scripts": ["src/background.js"]
},
*/

我希望这对你也有用。

在 Chrome 20.0.1132.57 m 的 Windows 7中,一个 HTML 背景页面对我来说不起作用,同样的错误:

Port error: Could not establish connection. Receiving end does not exist. miscellaneous_bindings:232

我尝试使用 background.js脚本,其内容如下:

chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// May be empty.
});
});

在我的内容脚本中的 解决了即时 onDisconnect:

port = chrome.extension.connect();
port.onDisconnect.addListener(function (event) {
// Happened immediately before adding the proper backend setup.
// With proper backend setup, allows to determine the extension being disabled or unloaded.
});

正确的代码来自 Chromium Extended 消息传递示例: Http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/timer/page.js?view=markup

这个示例还包含作为 sendRequest后端的第二部分,但我还没有亲自测试它:

chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
// Don't know if it may be empty or a sendResponse call is required.
});

问题可能是 sendRequest()onRequest已经被弃用并被 sendMessage()onMessage所取代。自从最近的 Chrome 20更新以来,它们似乎已经完全消失了。

关于 消息传递的官方文档甚至不再提到 sendRequest()

这里有一个链接,其中文件的变化一点点: http://codereview.chromium.org/9965005/

这并不总是原因,但如果你有一个错误在你的 background.js,你应该检查这个链接:

Inspect views: _generated_background_page.html

扩展页面中,它将显示任何 JavaScript 错误。

这阻碍了我建立关系。

尝试将一些连接脚本注入到 URL 为 铬://* Https://chrome.google.com/* 的选项卡中,当在后台页中连接这些选项卡时,

比如说

chrome.tabs.connect(tab.id).postMessage(msg)

然后将抛出

Port error: Could not establish connection. Receiving end does not exist.

这些页面不允许注入内容脚本,连接将立即断开。

所以,检查 url 并且不连接这些选项卡,那么异常就不会被抛出

经过一段时间的调查,我发现我的案子有问题。

我还得到了:

Port error: Could not establish connection. Receiving end does not exist.

在解释之前,我想说我正在使用 发送信息在信息上进行交流。

对于我来说,当我从后台页面发送一条消息到内容脚本正在运行的一个选项卡时,就会出现这个错误。

我的分机只能在 youtube 打开的标签上运行。 因此,当我改变一些首选项时,我会查看打开了哪些选项卡,并发送消息来更新更新的首选项。

在正常情况下,它工作得很好,但是如果我有 n (n > = 1)个标签,并且 youtube 是打开的。我点击“重新加载”按钮的扩展,我改变了一些... youtube 标签不刷新,他们失去了消息监听器,所以我得到这个错误。

看起来这很正常。

如果我在扩展重载后刷新 youtube 标签页,我不会得到这个错误。

我找到了一个解决方案,它可能不适用于所有情况:

当我遇到这个问题时,我的代码是:

chrome.tabs.sendMessage(tabId, {proprName: proprName, newValue: newValue}, function(response) {});

现在我的代码是:

chrome.tabs.sendMessage(tabId, {proprName: proprName, newValue: newValue});

对于我来说,我不需要响应回调,因为它没有响应,所以出现了这个错误。

我也使用 sendMessageonMessage进行通信,在我的工作流程中,我首先从 injected.js 发送一条消息到 backound.js,然后我也得到了这个错误:

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

因此,我决定使用响应功能(如 ) ,如果背景没有响应,我继续尝试与 setTimeout这样。

背景 Js

...
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
...
//some code


sendResponse({status: 'everything ok'})
return true;
});

注射

var myInjectedFunctionality = function() {


chrome.extension.sendMessage({method: "Steroids:loadScripts"}, function(res) {
if(res && res.status) {
} else {
setTimeout(myInjectedFunctionality, 3000);
}
});
};
myInjectedFunctionality();

我的代码现在运行正常,所以我认为解释很容易查看。当 Chrome 把你的代码注入到你想要的页面时,它不会准备 Backound.js 和连接的东西,所以没有人会监听你发送的消息,所以如果没有人监听,就像我一样继续尝试。

查阅最新的手册: Http://developer.chrome.com/extensions/messaging.html

注意: 如果多个页面正在监听 onMessage 事件,则只有 首先为特定事件调用 sendResponse ()将在 发送响应。对该事件的所有其他响应将是 被忽略了。

关闭标签页,只留下一页,然后检查。对我来说,这就是问题所在。

如果您遇到问题,主要是因为您引用的是过时的文档,请更新它!

访问: Chrome 扩展: messaging.html

我看到这个问题,我的内容脚本没有加载,所以发布消息从来没有发生过。

问题在于我打开了后台脚本检查器,只是推送 Cmd + R (刷新) ,但是在我的 manifest.json中有一个 bug。当我实际转到扩展页面并重新加载该页面时,我得到了显示清单错误的警报。

基本上,我看到这一点是因为我的内容脚本从来没有加载在第一位,我以为我刷新我的清单,但我没有。

现在面临着同样的问题。

//这是我以前的 背景 Js:

chrome.runtime.onInstalled.addListener(function () {
//some other code here
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.downloads.download({
url: message.url,
conflictAction: 'uniquify',
saveAs: false
});
}
});});//(Sorry, I tried but failed to put the last bracket on next line)

你看,当安装上的事件发生时,就会触发 AddListener,当我把它从这个作用域中取出来时,我的代码如下所示:

chrome.runtime.onInstalled.addListener(function () {
//some other code here
});
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.downloads.download({
url: message.url,
conflictAction: 'uniquify',
saveAs: false
});
}
});

现在已经很好用了,希望对你有所帮助。

我在使用 manifest_version: 2chrome.runtime.sendMessage时看到了这个错误。我从一个网页连接到扩展,而不是在扩展内。

解决方案是确保在 Manif.json 中的 externally_connectable.matches数组中有正确的值。您需要列出希望能够连接到扩展的 URL。见 https://developer.chrome.com/extensions/manifest/externally_connectable#without-externally-connectable

清单2.0和 sendMessage 用例相当简单:

如果您尝试在弹出窗口中使用 sendMessage,并且没有在后台脚本结束上设置侦听器,或者侦听器以某种方式被删除,就会发生这种情况。

我说的听众是指 chrome.runtime.onMessage.addListener

我把 chrome.runtime.sendMessagechrome.runtime.onMessage.addEventListener的内容脚本到 window.onload或自执行功能和它的工作。 在清单上我用了

“背景”: { “ script”: [“ backound.js”] , “顽固”: 假的 } ,

Manif_ version: 2. 希望能有帮助。

这里的一些其他的答案有很好的调试建议或小块的谜题,但是如果你想像我这样的 注入(第三方)网页,那么没有答案在这里列出正确的组件。

有四个步骤:

  • 一个 外部后台监听器,
  • 前台消息发送者,
  • 为消息发送方注入扩展名 id
  • 还有清单上的一条规则,把所有东西联系在一起。

下面的例子应该是所有您需要的东西,以允许您注入一个 js,将来自 google.com 上任何页面的消息发送到您自己的扩展

宣言 Json中,首先需要添加消息传递规则 这里描述的:

"externally_connectable": {
"matches": ["*://*.google.com/*"]
}

然后在你的 背景脚本或页面,你需要一个 外部侦听器 (< strong > Not 常规 chrome.runtime.onMessage.addListener,在 msot 答案中提到过),这是 这里描述的:

chrome.runtime.onMessageExternal.addListener( (request, sender, sendResponse) => {
console.log("Received message from " + sender + ": ", request);
sendResponse({ received: true }); //respond however you like
});

一旦你有了这些部件,你可以像平常一样使用 信息发送者,但是首先使用 分机号码作为第一个参数:

chrome.runtime.sendMessage(myExtId, { /* whatever you want to send goes here */ },
response => {
/* handle the response from background here */
}
);

如果您不知道如何获取我用作第一个参数的外部 id,您可以使用如下 注入你的分机号码。这是必需的,因为 Chrome.runtime.id@@扩展名 _ id都不能在注入的脚本中工作:

//create a script tag to inject, then set a variable with the id in that script
let idScript = document.createElement("script");
idScript.setAttribute("type", "application/javascript");
idScript.textContent = 'var myExtId = "' + chrome.runtime.id +'";';
let parent = ( document.head || document.documentElement );
parent.insertBefore( idScript, parent.firstChild );


//inject and run your other script here


idScript.remove(); //then cleanup

因为我们将其设置为 Var,所以其他脚本现在可以直接访问该值

如果消息处理位于弹出窗口或 html 页面中,并不总是可见,在发送任何消息之前,我都会检查弹出窗口是否可见,如下所示:

function isPopupVisible() { //required for firefox before sending any message ore we get the stupid message 'receiveing end does not exist'
var views = chrome.extension.getViews({ type: "popup" }); //https://stackoverflow.com/questions/8920953/how-determine-if-the-popup-page-is-open-or-not
if (views.length > 0) {
console.log("Popup is visible");
return true;
}
return false;
}

我遇到了这个问题,因为我在 backound.js 中添加了一个侦听器,当调用它时,它会向弹出页面发送一条消息,用于查看状态更新。虽然有时会调用侦听器,但弹出式页面实际上并不存在。我在发送消息之前检查确保弹出页面存在并避免这个问题。

检查你的 JavaScript 代码,他们可能是一个错误。我已经在我的发现

跟踪 Nick Cardosos 的响应,随着模块脚本、 v3清单等的出现..。

启用模块化的背景(Manif.json) :

  "background": {
"service_worker": "background/index.mjs",
"type": "module"
},

允许访问内容模块(Manif.json) :

  "web_accessible_resources": [
{
"resources": [
"manifest.json",
"src/index.mjs",
],
...
}
],

定义根内容模块:

  "content_scripts": [
{
"js": [ "extension.js" ],
...
}
],

向客户端注入一个模块(来自 extsion.js) :

document.querySelector('head').appendChild(
Object.assign(document.createElement('script'), {
type: 'module',
src: chrome.runtime.getURL('./src/index.mjs'),
}),
);

从模块中获取扩展 ID (src/index.mjs) :

const extensionId = new URL(import.meta.url).hostname

发送消息(./src/index.mjs 或任何其他模块) :

export const sendMessage = (message) => new Promise((resolve, reject) => {
try {
chrome.runtime.sendMessage(
extensionId,
message,
(response) => {
if (response?.isError === true) {
reject(Object.assign(
new Error(response.message),
response,
));
} else {
resolve(response);
}
},
);
} catch (e) {
reject(e);
}
});


/* ... */


const responsePayload = await sendMessage(messagePayload);

接收消息并发送响应(./back/index.mjs) :

export const onMessageExternal = (listener) => {
chrome.runtime.onMessageExternal.addListener(
async (messagePayload, sender, sendResponse) => {
try {
const response = await listener(messagePayload, sender);
sendResponse(response);
} catch (e) {
const { message, stack, name } = e;
// How you wrap errors is up to you, but the client
// and server must agree on the contract.
sendResponse({
isError: true,
message,
stack,
name,
});
}
},
);
};


/* ... */


onMessageExternal(async (messagePayload, sender) => {
console.log(messagePayload, sender);
return handleMessage(messagePayload);
});

重要的是要注意,如果你不调用 sendResponse,客户的承诺将永远不会解决。这就是为什么我把 sendMessageonMessageExternal包起来,这样他们就可以适当地处理。