多个chrome.runtime.onMessage-Listeners-断开连接的端口错误
Multiple chrome.runtime.onMessage-Listeners - disconnected port error
我正在开发一个chrome扩展,该扩展使用indexedDB Wrapper Dexie、几个jQuery库和syncfusions eGrid来显示和修改数据库。我知道这个问题以前被问过好几次,但现在我发现了一些奇怪的行为。
我的设置:
- 背景脚本
- 内容脚本(注入网站)
- index.html(用于显示网格)
- manifest.json
当我重新加载我的扩展时,一切都很好。我在内容脚本中注入了一个可滚动的名称列表。当我重新加载选项卡时,这也起作用。但当我在之前打开index.html(官方文档中的popup.html)时,来自后台的sendResponse脚本在一段时间后停止工作。重新加载选项卡将没有帮助。我搜索了几个小时,在谷歌的错误追踪器上发现了很多类似的案例和一些条目,他们声称这个问题已经解决了。我还知道,如果我有类似indexedDB的异步函数,那么我必须使用return true。
因此,为了给你更多的信息,我将列出我的缩短脚本。
内容脚本
chrome.runtime.sendMessage({greeting: 'getNames'},function(response){
$('.names-container').append(response.farewell);
});
chrome.runtime.sendMessage({greeting: 'getData'+name},function(name){
chrome.runtime.sendMessage({greeting: 'delete'},function(response){
console.log(response.farewell);
});
chrome.runtime.sendMessage({greeting: 'set'}, function(response) {
console.log(response.farewell);
});
});
背景脚本
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.greeting == 'getNames'){
// Get array of names from idb and send it back
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting.indexOf('getData') >= 0){
// get more information for selected name
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting == 'delete'){
// further processing to delete some stuff
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting == 'set'){
// synchronous function
// do something ...
return false;
} else {
// Do something
}
//return true;
});
funtion indexhtml(){
chrome.runtime.sendMessage(
"notifications",
function (response) {
console.log(response);
}
);
}
Index.html
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if(request == 'notifications'){
notifications();
}
sendResponse("Message received from background-page for "+request);
});
清单
{
"manifest_version": 2,
"name": "MyExtension",
"description": "Some desc...",
"version": "0.2",
"background": {
"scripts": ["js/jquery-2.1.4.min.js", "js/background.js", "...",
"persistent": true
},
"default_locale": "en",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-2.1.4.min.js"]
},
{
"matches": ["https://domain.tld/*"],
"js": ["js/jquery-2.1.4.min.js", "js/contentscript.js"],
"css" : ["css/contentscript.css",
"run_at": "document_start"
}
],
"icons": {
"16": "images/icon-16x16.png",
"48": "images/icon-48x48.png",
"128": "images/icon-128x128.png"
},
"browser_action": {
"default_icon": "images/icon-128x128.png"
},
"permissions": [
"cookies", "tabs", "alarms", "webRequest", "webRequestBlocking",
"contextMenus", "<all_urls>", "storage"
],
"content_security_policy": "script-src 'self' 'unsafe-eval';
object-src 'self'"
}
我很难调试这种行为,因为我不知道错误Attempting to use a disconnected port object
何时出现。在执行sendResponse之后,并且只有在index.html打开的情况下,端口才会正确关闭。
最后是缩短的错误消息:
Error: Attempting to use a disconnected port object
at Error (native)
at PortImpl.postMessage (extensions::messaging:65:22)
at Port.publicClass.(anonymous function) [as postMessage] (extensions::utils:94:26)
at responseCallback (extensions::messaging:163:16)
idb函数是定制的,不会像我在这里写的那样工作,但我只想展示我在那里做什么。当结果可用时,我使用.then()
到sendReponse
,如果异步,则使用return true;
等待结果。我还在每个脚本中搜索了onMessage
和sendMessage
。列出的与onMessage/sendMessage相关的函数都是我正在使用的,它们在其他地方没有使用。我正在使用indexhtml()
的计时器在指定的时间间隔内保存一个包含通知的数组,然后在index.html执行一个函数来重新加载通知。
index.html选项卡通过浏览器打开操作:
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.create({url: chrome.extension.getURL('index.html')});
});
好吧,在添加了越来越多的调试之后,我自己找到了答案。这里的问题是,我使用了多(2)个onMessage监听器。没有特定的监听器只监听发送到我的内容页面(index.html)的消息。每次我打开index.html时,如果在我的内容脚本中使用sendMessage,就会首先调用额外的onMessage监听器。我不知道这个嵌入到index.html中的onMessage Listener每次都会被调用。然后,我在内容脚本中更改了sendMessage的目的地,得到了相同的结果。谷歌文档中也有关于这个主题的注释:
注意:如果多个页面正在侦听onMessage事件,则只有第一个为特定事件调用sendResponse()的页面才能成功发送响应。将忽略对该事件的所有其他响应。
此处链接
第二个问题是,我在if子句之外使用了sendResponse,这样每次都会调用它。所以最后我只需要把sendResponse放在if子句中,这样只有当后台页面的指定消息通过sendMessage被调用时,它才会被调用。
背景脚本
- 通过搜索chrome获取tab.id-extension://extid/index.html
- 仅将消息发送到index.html
chrome.windows.getAll({populate:true},function(windows){
windows.forEach(function(window){
window.tabs.forEach(function(tab){
if(tab.url.indexOf(chrome.extension.getURL('index.html')) >= 0){
chrome.tabs.sendMessage(tab.id,{ greeting: "notifications"}, function(response){
console.log(response);
});
}
});
});
});
Index.html
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message.greeting == "notifications-trades"){
Notifications();
sendResponse("Message received from bg "+message.greeting);
//if async add return true;
} else {
//Do something
}
});
- 在node.js中写入ECONNRESET错误和套接字连接检查
- JavaScript和Java WebSocket SSL连接错误
- 模拟连接错误
- 如何防止“;错误:连接ECONNREFUSED”;
- 在javascript中调用seam远程函数时处理连接错误
- Webrtc和socket.io:createanswer()总是有一个错误.为什么?我的代码连接了两个对等体,但其中只
- socket.io:断开连接事件 - “传输关闭”、“客户端命名空间断开连接”、“传输错误”和“强制关闭”
- 解决节点中的“本地主机意外关闭连接”错误
- Postgresql错误:连接已终止
- 如何在node.js中设置mysql连接,以在带无符号整数的算术上抛出超出范围的错误
- Chrome 消息传递.未捕获错误:连接到扩展时出错
- “错误:连接 ENOENT”当节点快速中间件发出 POST 请求(使用节点请求库)时
- 节点.js npm 安装错误连接超时
- 错误连接拒绝http://localhost:3000/socket.io/socket.io.js.
- 为什么我的查询在pgAdming上工作,但当我从服务器执行它时,我得到一个查询错误(错误:连接终止)
- Openshift和外部mysql数据库与node-mysql(错误:连接ECONNREFUSED)
- 500服务器错误(连接重置),JS文件获胜't负载
- 错误:连接[localhost:27017]失败
- Node.js类型错误连接-flash
- 程序失败- html和javascript之间的错误连接