Ich arbeite an einer Chrome-Erweiterung, die die indexedDB-Wrapper Dexie, mehrere jQuery-Bibliotheken und syncfusions eGrid zum Anzeigen und Ändern der Datenbank verwendet. Ich weiß, dass diese Frage schon mehrmals gestellt wurde, aber jetzt entdeckte ich ein seltsames Verhalten.Mehrere chrome.runtime.onMessage-Listeners - getrennte Port-Fehler
Mein Setup:
- Hintergrund-Skript
- content-Skript (in eine Webseite injiziert)
- index.html (für das Grid Anzeigen)
- manifest.json
Wenn ich meine Erweiterung neu lade, ist alles in Ordnung. Ich gebe eine scrollbare Liste von Namen mit meinem Inhaltsskript ein. Das funktioniert auch, wenn ich den Tab neu lade. Aber als ich die index.html vor öffnete (popup.html in der offiziellen Dokumentation) die sendResponse von background-script funktioniert nach einiger Zeit nicht mehr. Das erneute Laden der Registerkarte würde dann nicht helfen. Ich suchte stundenlang, fand viele ähnliche Fälle und einige Einträge zu googles bugtracker, wo sie behaupteten, dass dieses Problem bereits behoben sei. Ich weiß auch, dass ich Return true verwenden muss, wenn ich async Funktionen wie mit indexedDB habe.
Um Ihnen weitere Informationen zu geben, werde ich meine verkürzten Skripte auflisten.
Inhalt-Script
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);
});
});
Background-Script
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
{
"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'"
}
Es ist schwierig für mich, dieses Verhalten zu debuggen, da ich genau kann nicht wissen, wann die Fehler Attempting to use a disconnected port object
erscheint. Es sieht so aus, als würde der Port nicht korrekt geschlossen, nachdem die sendResponse ausgeführt wurde und nur wenn die index.html geöffnet wurde.
Schließlich ist die verkürzte Fehlermeldung:
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)
Die IDB-Funktionen sind individuell und won't Arbeit, wie ich sie hier geschrieben habe, aber ich will nur zeigen, was ich bin es zu tun. Ich verwende .then()
bis sendReponse
, wenn das Ergebnis verfügbar ist und return true;
auf das Ergebnis warten, wenn async. Ich habe auch jedes Skript nach onMessage
und sendMessage
durchsucht. Die aufgelisteten Funktionen, die sich auf onMessage/sendMessage beziehen, sind alles, was ich verwende, sie werden nicht woanders verwendet. Ich verwende einen Timer für indexhtml()
, um ein Array zu speichern, das die Benachrichtigungen in einem bestimmten Intervall enthält, und dann eine Funktion in index.html auszuführen, um die Benachrichtigungen neu zu laden.
Der Index.html Tab wird über browserAction geöffnet:
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.create({url: chrome.extension.getURL('index.html')});
});