Signatur
Beschreibung
Das message-Ereignis tritt auf, wenn auf einem BroadcastChannel mit demselben Kanalnamen eine Nachricht eintrifft. Der Sender kann ein anderes Tab, ein anderes Fenster, ein iframe oder ein Worker (Dedicated, Shared, Service Worker) sein, sofern er zum gleichen Ursprung (Origin) gehört. Der sendende Kanal selbst bekommt seine eigene Nachricht nicht.
Den Handler registriert man entweder mit channel.addEventListener("message", handler) oder über die Eigenschaft channel.onmessage = handler. Der Handler erhält ein MessageEvent. Die gesendeten Daten stehen in event.data. Sie wurden mit dem Structured-Clone-Algorithmus kopiert, deshalb sind auch Objekte, Arrays, Map, Set, Date oder Blob möglich.
Typische Einsätze sind das Abgleichen des Zustands zwischen Tabs (Abmelden in allen Tabs, Warenkorb-Aktualisierung, Theme-Wechsel), das Invalidieren von Caches oder Nachrichten vom Service Worker an alle offenen Seiten. Im Gegensatz zu window.postMessage() braucht man keine Referenz auf das Zielfenster, denn jeder Teilnehmer abonniert einfach den Kanalnamen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier "message". |
|
| $handler Pflicht | (event: MessageEvent) => void | Callback, der ein MessageEvent bekommt. Wichtige Eigenschaften: data (die geklonte Nachricht) und origin. source und ports sind bei BroadcastChannel immer null bzw. leer. |
|
| $options | boolean|AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal (AbortSignal zum Entfernen). |
Rückgabewert
addEventListener() gibt nichts zurück. Der Handler erhält ein MessageEvent.Beispiele
Abmelden in allen Tabs synchronisieren
// In jedem Tab ausführen
const authChannel = new BroadcastChannel("auth");
authChannel.addEventListener("message", (event) => {
if (event.data?.type === "logout") {
console.log("Abgemeldet in anderem Tab – leite um…");
window.location.href = "/login";
}
});
// Beim Klick auf „Abmelden“ im aktuellen Tab
document.querySelector("#logout")?.addEventListener("click", () => {
authChannel.postMessage({ type: "logout", at: Date.now() });
window.location.href = "/login";
});
onmessage-Eigenschaft und Aufräumen mit close()
const themeChannel = new BroadcastChannel("theme");
themeChannel.onmessage = ({ data }) => {
document.documentElement.dataset.theme = data.theme;
console.log(`Theme gewechselt auf: ${data.theme}`);
};
// Andere Tabs informieren
themeChannel.postMessage({ theme: "dark" });
// Listener entfernen und Kanal schließen, z. B. beim Verlassen der Seite
window.addEventListener("pagehide", () => {
themeChannel.onmessage = null;
themeChannel.close();
});
Listener per AbortSignal entfernen
const cartChannel = new BroadcastChannel("cart");
const controller = new AbortController();
cartChannel.addEventListener(
"message",
(event) => {
const { items } = event.data;
console.log(`Warenkorb aktualisiert: ${items.length} Artikel`);
},
{ signal: controller.signal }
);
// Später: Listener abmelden, ohne die Handler-Referenz zu brauchen
controller.abort();
Service Worker benachrichtigt alle Seiten
// sw.js
const swChannel = new BroadcastChannel("sw-updates");
self.addEventListener("activate", () => {
swChannel.postMessage({ type: "new-version", version: "2.1.0" });
});
// main.js (Seite)
const updates = new BroadcastChannel("sw-updates");
updates.addEventListener("message", ({ data }) => {
if (data.type === "new-version") {
console.log(`Neue Version ${data.version} verfügbar – bitte neu laden.`);
}
});
// Wichtig · Fallstricke
- Kein Echo: Die sendende
BroadcastChannel-Instanz bekommt ihre eigene Nachricht nicht. Eine zweite Instanz mit gleichem Namen im selben Kontext bekommt sie aber schon. - Nur gleicher Ursprung: Die Kommunikation funktioniert nur zwischen Kontexten mit identischem Origin (Schema, Host, Port). Außerdem trennen Browser mit Storage-Partitionierung die Kanäle nach Top-Level-Site, sodass ein eingebettetes Drittanbieter-iframe andere Kanäle sieht als dieselbe Seite als Top-Level-Dokument.
- Nicht klonbare Daten: Funktionen, DOM-Knoten und Klasseninstanzen samt Prototyp lassen sich nicht übertragen. Ist die Deserialisierung beim Empfänger nicht möglich, wird statt
messagedas Ereignismessageerrorausgelöst.postMessage()selbst wirft bei nicht klonbaren Werten eineDataCloneError-Ausnahme. - Sicherheit: Jedes Skript desselben Ursprungs kann auf dem Kanal senden. Behandle
event.datadeshalb als nicht vertrauenswürdig: Struktur prüfen und niemals ungeprüft ininnerHTMLoderevalübernehmen. - Keine Zustellgarantie und keine Pufferung: Nachrichten erreichen nur Kontexte, die in diesem Moment einen offenen Kanal haben. Für dauerhaften Zustand zusätzlich
localStorageoder IndexedDB verwenden. - Aufräumen: Mit
close()den Kanal schließen, wenn er nicht mehr gebraucht wird. Ein offener Kanal kann den Back/Forward-Cache verhindern und hält Ressourcen fest. - Kompatibilität: Wird von Chrome 54+, Firefox 38+, Edge 79+ und Safari 15.4+ unterstützt, in Workern ebenso. Ältere Safari-Versionen brauchen einen Ausweichweg, etwa über das
storage-Ereignis.