Ich versuche, Nachrichten zwischen Inhaltsskript und der Erweiterung weiterzuleiten
Hier ist, was ich in Content-Skript habe
chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
console.log(response)
});
Und im Hintergrundskript habe ich
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.type == "getUrls"){
getUrls(request, sender, sendResponse)
}
});
function getUrls(request, sender, sendResponse){
var resp = sendResponse;
$.ajax({
url: "http://localhost:3000/urls",
method: 'GET',
success: function(d){
resp({urls: d})
}
});
}
Wenn ich nun die Antwort vor dem Ajax-Aufruf in der Funktion getUrls
sende, wird die Antwort erfolgreich gesendet, aber in der Erfolgsmethode des Ajax-Aufrufs wird sie beim Senden der Antwort nicht gesendet, wenn ich gehe Beim Debuggen sehe ich, dass der Port im Code für die Funktion sendResponse
null ist.
Von die Dokumentation für chrome.runtime.onMessage.addListener
:
Diese Funktion wird ungültig, wenn der Ereignis-Listener zurückgibt, es sei denn, Sie geben vom Ereignis-Listener true zurück, um anzuzeigen, dass Sie eine Antwort asynchron senden möchten (dies hält den Nachrichtenkanal zum anderen Ende hin offen, bis sendResponse aufgerufen wird).
Sie müssen also nach dem Aufruf von getUrls
nur noch return true;
Hinzufügen, um anzuzeigen, dass Sie die Antwortfunktion asynchron aufrufen.
Die akzeptierte Antwort ist richtig. Ich wollte nur Beispielcode hinzufügen, der dies vereinfacht. Das Problem ist, dass die API (meiner Ansicht nach) nicht gut gestaltet ist, da wir Entwickler wissen müssen, ob eine bestimmte Nachricht asynchron behandelt wird oder nicht. Wenn Sie mit vielen verschiedenen Nachrichten umgehen, wird dies zu einer unmöglichen Aufgabe, da Sie nie wissen, ob eine übergebene sendResponse im Grunde genommen asynchron heißt oder nicht. Bedenken Sie:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
handleMethod1(sendResponse);
}
Wie kann ich herausfinden, ob der Anruf im Grunde handleMethod1
Asynchron ist oder nicht? Wie kann jemand, der handleMethod1
Ändert, wissen, dass ein Anrufer durch die Einführung einer asynchronen Funktion unterbrochen wird?
Meine Lösung lautet:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
var responseStatus = { bCalled: false };
function sendResponse(obj) { //dummy wrapper to deal with exceptions and detect async
try {
sendResponseParam(obj);
} catch (e) {
//error handling
}
responseStatus.bCalled= true;
}
if (request.method == "method1") {
handleMethod1(sendResponse);
}
else if (request.method == "method2") {
handleMethod2(sendResponse);
}
...
if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
return true;
}
});
Dadurch wird der Rückgabewert automatisch verarbeitet, unabhängig davon, wie Sie die Nachricht verarbeiten. Beachten Sie, dass dies voraussetzt, dass Sie nie vergessen, die Antwortfunktion aufzurufen. Beachten Sie auch, dass Chrom dies für uns hätte automatisieren können, ich verstehe nicht, warum sie dies nicht getan haben.
Sie können meine Bibliothek https://github.com/lawlietmester/webextension verwenden, um diese Funktion auf Chrome und FF mit Firefox-Art und Weise ohne Rückrufe auszuführen.
Ihr Code sieht folgendermaßen aus:
Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;
$.ajax({
'url': "http://localhost:3000/urls",
'method': 'GET'
}).then( urls => { resolve({ urls }); });
}) );