runtime.onMessage

Verwenden Sie dieses Ereignis, um Nachrichten von einem anderen Teil Ihrer Erweiterung zu empfangen.

Einige Anwendungsbeispiele sind:

  • in einem Content-Skript, um Nachrichten von einem Hintergrundskript zu empfangen.
  • in einem Hintergrundskript, um Nachrichten von einem Content-Skript zu empfangen.
  • in einer Optionsseite oder einem Popup-Skript, um Nachrichten von einem Hintergrundskript zu empfangen.
  • in einem Hintergrundskript, um Nachrichten von einer Optionsseite oder einem 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 Content-Skript zu senden) tabs.sendMessage().

Hinweis: Vermeiden Sie es, mehrere onMessage()-Listener für denselben Nachrichtentyp zu erstellen, da die Reihenfolge, in der die Listener ausgelöst werden, nicht garantiert ist.

Wenn Sie die Zustellung einer Nachricht an einen bestimmten Endpunkt garantieren möchten, verwenden Sie den verbindungsbasierten Ansatz, um Nachrichten auszutauschen.

Zusammen mit der Nachricht selbst erhält der Listener folgende Informationen:

  • ein sender Objekt, das Details über den Absender der Nachricht enthält.
  • eine sendResponse() Funktion, die verwendet werden kann, um eine Antwort an den Absender zu senden.

Sie können eine synchronisierte Antwort auf die Nachricht senden, indem Sie die sendResponse() Funktion innerhalb Ihres Listeners aufrufen. Siehe ein Beispiel.

Um eine asynchrone Antwort zu senden, gibt es zwei Optionen:

  • Geben Sie true vom Ereignislistener zurück. Dadurch bleibt die sendResponse() Funktion nach der Rückkehr des Listeners gültig, sodass Sie sie später aufrufen können. Siehe ein Beispiel.

    Warnung: Präfixen Sie die Funktion nicht mit async. Das Präfixieren mit async ändert die Bedeutung zu Senden einer asynchronen Antwort mit einem Promise, was im Wesentlichen dasselbe ist wie sendResponse(true).

  • Geben Sie ein Promise vom Ereignislistener zurück, und lösen Sie es auf, wenn Sie die Antwort haben (oder lehnen Sie es im Falle eines Fehlers ab). Siehe ein Beispiel.

Syntax

js
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)

Hört auf, dieses Ereignis zu überwachen. Das listener-Argument ist der zu entfernende Listener.

hasListener(listener)

Überprüft, ob mindestens ein Listener für dieses Ereignis registriert ist. Gibt true zurück, wenn es überwacht wird, andernfalls false.

addListener-Syntax

Parameter

listener

Die Funktion, die aufgerufen wird, wenn dieses Ereignis auftritt. Die Funktion erhält folgende Argumente:

message

object. Die Nachricht selbst. Dies ist ein serialisierbares Objekt (siehe Datenklon-Algorithmus).

sender

Ein runtime.MessageSender Objekt, das den Absender der Nachricht repräsentiert.

sendResponse

Eine Funktion, die höchstens einmal aufgerufen wird, um eine Antwort auf die message zu senden. Die Funktion nimmt ein einziges Argument an, das jedes serialisierbare Objekt sein kann (siehe Datenklon-Algorithmus). Dieses Argument wird an den Nachrichtenabsender zurückgegeben.

Wenn Sie mehr als einen onMessage()-Listener im selben Dokument haben, darf 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:

  • behalten Sie entweder eine Referenz auf das sendResponse()-Argument und geben Sie true von der Listener-Funktion zurück. Sie können dann sendResponse() aufrufen, nachdem die Listener-Funktion zurückgekehrt ist.

  • oder geben Sie ein Promise von der Listener-Funktion zurück und lösen Sie das Promise auf, wenn die Antwort bereit ist. Dies ist die bevorzugte Methode.

    Hinweis: Promise als Rückgabewert wird in Chrome nicht unterstützt, bis Chrome bug 1185241 gelöst ist. Als Alternative return true und verwenden Sie sendResponse.

Die listener-Funktion kann entweder einen Boolean oder ein Promise zurückgeben.

Hinweis: Wenn Sie eine asynchrone Funktion an addListener() übergeben, gibt der Listener ein Promise für jede empfangene Nachricht zurück, was verhindert, dass andere Listener antworten:

js
// nicht so machen
browser.runtime.onMessage.addListener(async (data, sender) => {
  if (data.type === "handle_me") {
    return "done";
  }
});

Wenn Sie möchten, dass der Listener nur auf Nachrichten eines bestimmten Typs reagiert, müssen Sie den Listener als nicht-async Funktion definieren und nur für die Nachrichten ein Promise zurückgeben, auf die der Listener reagieren soll – und ansonsten false oder undefined zurückgeben:

js
browser.runtime.onMessage.addListener((data, sender) => {
  if (data.type === "handle_me") {
    return Promise.resolve("done");
  }
  return false;
});

Browser-Kompatibilität

BCD tables only load in the browser

Beispiele

Einfaches Beispiel

Dieses Content-Skript hört auf Klick-Ereignisse auf der Webseite. Wenn der Klick auf einen Link erfolgte, sendet es eine Nachricht an die Hintergrundseite mit der Ziel-URL:

js
// content-script.js

window.addEventListener("click", notifyExtension);

function notifyExtension(e) {
  if (e.target.tagName !== "A") {
    return;
  }
  browser.runtime.sendMessage({ url: e.target.href });
}

Das Hintergrundskript hört auf diese Nachrichten und zeigt eine Benachrichtigung mit der notifications API an:

js
// 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 Content-Skript sendet eine Nachricht an das Hintergrundskript, wenn der Benutzer auf die Seite klickt. Es protokolliert auch alle Antworten, die vom Hintergrundskript gesendet werden:

js
// 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 Hintergrundskripts, die eine Antwort synchron, von innen im Listener, sendet:

js
// 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 weitere Version, die Promise.resolve() verwendet:

js
// 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 unter Verwendung von sendResponse

Hier ist eine alternative Version des Hintergrundskripts 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.

js
// 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: Präfixen Sie die Funktion nicht mit async. Das Präfixieren mit async ä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 gelöst ist. Als Alternative return true und verwenden Sie sendResponse.

Dieses Content-Skript erhält den ersten <a>-Link auf der Seite und sendet eine Nachricht, um zu fragen, ob der Speicherort des Links ein Lesezeichen ist. Es erwartet eine Boolean-Antwort (true, wenn der Speicherort ein Lesezeichen ist, andernfalls false):

js
// 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 Hintergrundskript. Es verwendet bookmarks.search() um zu überprüfen, ob der Link ein Lesezeichen ist, was ein Promise zurückgibt:

js
// 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 ein Promise explizit konstruieren. Dieses eher konstruierte Beispiel sendet eine Antwort nach einer 1-Sekunden-Verzögerung, unter Verwendung von setTimeout():

js
// 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