runtime.onMessage
Verwenden Sie dieses Ereignis, um auf Nachrichten aus einem anderen Teil Ihrer Erweiterung zu lauschen.
Einige Anwendungsfälle sind:
- in einem Inhalts-Skript um Nachrichten von einem Hintergrund-Skript zu empfangen.
- in einem Hintergrund-Skript, um Nachrichten von einem Inhalts-Skript zu empfangen.
- in einem Einstellungs- oder Popup-Skript um Nachrichten von einem Hintergrund-Skript zu empfangen.
- in einem Hintergrund-Skript, um Nachrichten von einem Einstellungs- oder Popup-Skript zu empfangen.
Um eine Nachricht zu senden, die vom onMessage()
-Listener empfangen wird, verwenden Sie runtime.sendMessage()
oder (um eine Nachricht an ein Inhalts-Skript zu senden) tabs.sendMessage()
.
Hinweis:
Vermeiden Sie es, mehrere onMessage()
-Listener für den gleichen Nachrichtentyp zu erstellen, da die Reihenfolge, in der mehrere Listener aufgerufen werden, nicht garantiert ist.
Wenn Sie die Zustellung einer Nachricht an einen bestimmten Endpunkt garantieren möchten, verwenden Sie den verbindungsbasierten Ansatz zum Nachrichtenaustausch.
Zusammen mit der Nachricht selbst wird dem Listener Folgendes übergeben:
- ein
sender
-Objekt mit Details über den Nachrichtenabsender. - eine
sendResponse()
-Funktion, die verwendet werden kann, um eine Antwort an den Absender zurückzusenden.
Sie können eine synchrone Antwort auf die Nachricht senden, indem Sie die sendResponse()
-Funktion innerhalb Ihres Listeners aufrufen. Siehe das Beispiel für das Senden einer synchronen Antwort.
Um eine asynchrone Antwort zu senden, gibt es zwei Optionen:
- Geben Sie
true
aus dem Event-Listener zurück. Dies hält diesendResponse()
-Funktion nach der Rückgabe des Listeners gültig, sodass Sie sie später aufrufen können. Siehe das Beispiel für eine asynchrone Antwort mitsendResponse
.Warnung: Fügen Sie der Funktion nicht
async
als Präfix hinzu.async
als Präfix ändert die Bedeutung zu Senden einer asynchronen Antwort mit einem Promise, was im Wesentlichen dasselbe ist wiesendResponse(true)
. - Geben Sie ein
Promise
aus dem Event-Listener zurück, und lösen Sie es auf, wenn die Antwort bereit ist (oder lehnen Sie es im Falle eines Fehlers ab). [Siehe das Beispiel für eine asynchrone Antwort mit einem Promise.
Hinweis: Sie können auch einen verbindungsbasierten Ansatz zum Nachrichtenaustausch verwenden.
Syntax
browser.runtime.onMessage.addListener(listener)
browser.runtime.onMessage.removeListener(listener)
browser.runtime.onMessage.hasListener(listener)
Ereignisse haben drei Funktionen:
addListener(listener)
-
Fügt diesem Ereignis einen Listener hinzu.
removeListener(listener)
-
Beendet das Lauschen dieses Ereignisses. Das
listener
-Argument ist der Listener, der entfernt werden soll. hasListener(listener)
-
Überprüft, ob mindestens ein Listener für dieses Ereignis registriert ist. Gibt
true
zurück, wenn es lauscht, sonstfalse
.
addListener Syntax
Parameter
listener
-
Die Funktion, die aufgerufen wird, wenn dieses Ereignis eintritt. Der Funktion werden folgende Argumente übergeben:
message
-
object
. Die Nachricht. Dies ist ein serialisierbares Objekt (siehe Data cloning algorithm). sender
-
Ein
runtime.MessageSender
-Objekt, das den Absender der Nachricht repräsentiert. sendResponse
-
Eine Funktion, die höchstens einmal aufgerufen werden kann, um eine Antwort auf die
message
zu senden. Die Funktion nimmt ein Argument: jedes serialisierbare Objekt (siehe Data cloning algorithm). Dieses Argument wird an den Nachrichtenabsender zurückgegeben.Wenn Sie mehr als einen
onMessage()
-Listener im gleichen Dokument haben, kann nur einer eine Antwort senden.Um eine Antwort synchron zu senden, rufen Sie
sendResponse()
auf, bevor die Listener-Funktion zurückkehrt.Um eine Antwort asynchron zu senden, verwenden Sie eine der folgenden Optionen:
-
Geben Sie ein
Promise
aus der Listener-Funktion zurück und lösen Sie das Promise auf, wenn die Antwort bereit ist. Dies ist der bevorzugte Ansatz. -
Behalten Sie eine Referenz auf das
sendResponse()
-Argument und geben Sietrue
aus der Listener-Funktion zurück. Sie rufen dannsendResponse()
auf, nachdem die Listener-Funktion zurückgekehrt ist.Hinweis: Promise als Rückgabewert wird in Chrome nicht unterstützt, bis Chrome Bug 1185241 behoben ist. Alternativ geben Sie true zurück und verwenden Sie sendResponse.
-
Die
listener
-Funktion kann entweder ein Boolean oder einPromise
zurückgeben.Hinweis: Wenn Sie eine asynchrone Funktion an
addListener()
übergeben, gibt der Listener für jede empfangene Nachricht ein Promise zurück, was andere Listener daran hindert zu antworten:js// Machen Sie das nicht browser.runtime.onMessage.addListener(async (data, sender) => { if (data.type === "handle_me") { return "done"; } });
Angenommen, Sie möchten, dass der Listener nur auf Nachrichten eines bestimmten Typs reagiert. In diesem Fall müssen Sie den Listener als nicht asynchrone Funktion definieren und nur für die Nachrichten ein Promise zurückgeben, auf die der Listener reagieren soll — und sonst false oder undefined zurückgeben:
jsbrowser.runtime.onMessage.addListener((data, sender) => { if (data.type === "handle_me") { return Promise.resolve("done"); } return false; });
Beispiele
Einfaches Beispiel
Dieses Inhalts-Skript horcht auf Klick-Ereignisse auf der Webseite. Wenn der Klick auf einen Link erfolgt, sendet es eine Nachricht mit der Ziel-URL an die Hintergrundseite:
// content-script.js
window.addEventListener("click", notifyExtension);
function notifyExtension(e) {
if (e.target.tagName !== "A") {
return;
}
browser.runtime.sendMessage({ url: e.target.href });
}
Das Hintergrund-Skript horcht auf diese Nachrichten und zeigt eine Benachrichtigung mit der notifications
API an:
// background-script.js
browser.runtime.onMessage.addListener(notify);
function notify(message) {
browser.notifications.create({
type: "basic",
iconUrl: browser.extension.getURL("link.png"),
title: "You clicked a link!",
message: message.url,
});
}
Senden einer synchronen Antwort
Dieses Inhalts-Skript sendet eine Nachricht an das Hintergrund-Skript, wenn der Benutzer auf die Seite klickt. Es protokolliert auch jede vom Hintergrund-Skript gesendete Antwort:
// content-script.js
function handleResponse(message) {
console.log(`background script sent a response: ${message.response}`);
}
function handleError(error) {
console.log(`Error: ${error}`);
}
function sendMessage(e) {
const sending = browser.runtime.sendMessage({
content: "message from the content script",
});
sending.then(handleResponse, handleError);
}
window.addEventListener("click", sendMessage);
Hier ist eine Version des entsprechenden Hintergrund-Skripts, das eine Antwort synchron aus dem Listener sendet:
// background-script.js
function handleMessage(request, sender, sendResponse) {
console.log(`content script sent a message: ${request.content}`);
sendResponse({ response: "response from background script" });
}
browser.runtime.onMessage.addListener(handleMessage);
Und hier ist eine andere Version, die Promise.resolve()
verwendet:
// background-script.js
function handleMessage(request, sender, sendResponse) {
console.log(`content script sent a message: ${request.content}`);
return Promise.resolve({ response: "response from background script" });
}
browser.runtime.onMessage.addListener(handleMessage);
Senden einer asynchronen Antwort mit sendResponse
Hier ist eine alternative Version des Hintergrund-Skripts aus dem vorherigen Beispiel. Es sendet eine Antwort asynchron, nachdem der Listener zurückgekehrt ist. Beachten Sie return true;
im Listener: Dies teilt dem Browser mit, dass Sie beabsichtigen, das sendResponse
-Argument nach der Rückkehr des Listeners zu verwenden.
// background-script.js
function handleMessage(request, sender, sendResponse) {
console.log(`content script sent a message: ${request.content}`);
setTimeout(() => {
sendResponse({ response: "async response from background script" });
}, 1000);
return true;
}
browser.runtime.onMessage.addListener(handleMessage);
Warnung:
Fügen Sie der Funktion nicht async
als Präfix hinzu. async
als Präfix ändert die Bedeutung zu Senden einer asynchronen Antwort mit einem Promise, was im Wesentlichen dasselbe ist wie sendResponse(true)
.
Senden einer asynchronen Antwort mit einem Promise
Hinweis:
Promise als Rückgabewert wird in Chrome nicht unterstützt, bis Chrome Bug 1185241 behoben ist. Alternativ geben Sie true zurück und verwenden Sie sendResponse
.
Dieses Inhalts-Skript sucht den ersten <a>
-Link auf der Seite und sendet eine Nachricht, die fragt, ob der Standort des Links als Lesezeichen gespeichert ist. Es erwartet eine booleanische Antwort (true
, wenn der Standort als Lesezeichen gespeichert ist, sonst false
):
// content-script.js
const firstLink = document.querySelector("a");
function handleResponse(isBookmarked) {
if (isBookmarked) {
firstLink.classList.add("bookmarked");
}
}
browser.runtime
.sendMessage({
url: firstLink.href,
})
.then(handleResponse);
Hier ist das Hintergrund-Skript. Es verwendet bookmarks.search()
, um zu überprüfen, ob der Link als Lesezeichen gespeichert ist, was ein Promise
zurückgibt:
// background-script.js
function isBookmarked(message, sender, response) {
return browser.bookmarks
.search({
url: message.url,
})
.then((results) => results.length > 0);
}
browser.runtime.onMessage.addListener(isBookmarked);
Wenn der asynchrone Handler kein Promise zurückgibt, können Sie explizit ein Promise konstruieren. Dieses eher gekünstelte Beispiel sendet eine Antwort nach einer Verzögerung von 1 Sekunde unter Verwendung von setTimeout()
:
// background-script.js
function handleMessage(request, sender, sendResponse) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ response: "async response from background script" });
}, 1000);
});
}
browser.runtime.onMessage.addListener(handleMessage);
Beispielerweiterungen
Browser-Kompatibilität
Hinweis:
Diese API basiert auf der chrome.runtime
-API von Chromium. Diese Dokumentation ist von runtime.json
im Chromium-Code abgeleitet.