Signatur
Beschreibung
BroadcastChannel stellt einen einfachen Publish-/Subscribe-Mechanismus für alle Browsing-Kontexte (Tabs, Fenster, iframes) und Worker bereit, die zum selben Ursprung (Schema + Host + Port) gehören. Jeder Kontext, der mit new BroadcastChannel(name) einen Kanal mit demselben Namen öffnet, bekommt alle Nachrichten, die über diesen Kanal gesendet werden. Nur das sendende Objekt selbst bekommt seine Nachricht nicht.
Typische Anwendungsfälle sind das Synchronisieren des Anmeldestatus (Abmelden in einem Tab meldet alle Tabs ab), das Weitergeben von Einstellungen wie dem Dark Mode, das Invalidieren eines Caches oder die Abstimmung zwischen Service Worker und Seiten. Anders als bei window.postMessage() braucht man keine Referenz auf das Zielfenster. Anders als beim storage-Event lassen sich beliebige strukturiert klonbare Daten verschicken, ohne den localStorage als Umweg zu benutzen.
Wichtige Mitglieder:
name– der Kanalname (nur lesbar).postMessage(message)– sendet eine Nachricht an alle anderen Teilnehmer. Die Daten werden mit dem Structured Clone Algorithm kopiert.close()– trennt das Objekt vom Kanal und gibt die Ressourcen frei.- Die Events
messageundmessageerrorlassen sich überaddEventListener()oder die Eigenschaftenonmessageundonmessageerrorabonnieren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $channelName Pflicht | string | Name des Kanals (Parameter des Konstruktors new BroadcastChannel(channelName)). Alle Objekte mit gleichem Namen und gleichem Ursprung teilen sich einen Kanal. Andere Werte werden in einen String umgewandelt. |
Rückgabewert
BroadcastChannel-Instanz, die sofort mit dem benannten Kanal verbunden ist.Beispiele
Kanal erstellen, Nachrichten senden und empfangen
// In jedem Tab derselben Anwendung ausführen
const channel = new BroadcastChannel('app-events');
channel.addEventListener('message', (event) => {
console.log('Empfangen:', event.data);
});
// Sendet an alle ANDEREN Tabs – das eigene Objekt bekommt die Nachricht nicht
channel.postMessage({ type: 'greeting', text: 'Hallo aus Tab A' });
Logout in allen Tabs synchronisieren
const authChannel = new BroadcastChannel('auth');
const logout = async () => {
await fetch('/api/logout', { method: 'POST' });
authChannel.postMessage({ type: 'logout' });
location.assign('/login');
};
authChannel.onmessage = ({ data }) => {
if (data?.type === 'logout') {
// Andere Tabs leiten ebenfalls um
location.assign('/login');
}
};
document.querySelector('#logout-btn')?.addEventListener('click', logout);
Service Worker meldet Cache-Update an alle Seiten
// sw.js
const updates = new BroadcastChannel('cache-updates');
self.addEventListener('activate', () => {
updates.postMessage({ type: 'new-version', version: '2.1.0' });
});
// main.js (Seite)
const updatesChannel = new BroadcastChannel('cache-updates');
updatesChannel.onmessage = ({ data }) => {
if (data.type === 'new-version') {
console.log(`Version ${data.version} verfügbar – bitte neu laden.`);
}
};
Kanal sauber schließen und Fehler behandeln
const channel = new BroadcastChannel('live-data');
const onMessage = (event) => console.log('Daten:', event.data);
channel.addEventListener('message', onMessage);
channel.addEventListener('messageerror', (event) => {
console.error('Nachricht konnte nicht deserialisiert werden', event);
});
// Beim Verlassen der Ansicht aufräumen
window.addEventListener('pagehide', () => {
channel.removeEventListener('message', onMessage);
channel.close();
});
console.log(channel.name);
// Wichtig · Fallstricke
- Nur derselbe Ursprung: Andere Ursprünge und Subdomains werden nicht erreicht. Für Kommunikation über Ursprünge hinweg nimmt man
window.postMessage()mit Prüfung vonevent.origin. - Keine Rückmeldung: Es gibt weder eine Zustellbestätigung noch eine Liste der Empfänger. Ein Frage-Antwort-Protokoll muss man selbst bauen, zum Beispiel mit IDs in den Nachrichten.
- Kein Echo: Die sendende Instanz bekommt ihre eigene Nachricht nicht. Andere Instanzen mit demselben Namen im selben Kontext bekommen sie dagegen schon.
- Strukturiertes Klonen: Funktionen, DOM-Knoten und Klasseninstanzen samt Prototyp lassen sich nicht übertragen. Wer es versucht, bekommt eine
DataCloneError-Ausnahme.postMessage()nachclose()wirft einenInvalidStateError. Transferable-Objekte werden nicht unterstützt. - Speicherpartitionierung: In Drittanbieter-iframes teilen moderne Browser Kanäle zusätzlich nach der obersten Website auf. Dasselbe iframe unter verschiedenen Top-Level-Websites sieht deshalb nicht dieselben Nachrichten. Private Fenster sind vom normalen Modus getrennt.
- Sicherheit: Jedes Skript desselben Ursprungs kann mitlesen und Nachrichten schicken. Deshalb keine Geheimnisse wie Tokens übertragen und eingehende Daten vor der Verarbeitung prüfen, besonders bevor sie ins DOM geschrieben werden (XSS).
- Aufräumen:
close()aufrufen, wenn der Kanal nicht mehr gebraucht wird. Ein offener Kanal kann in manchen Browsern den Back/Forward-Cache verhindern und hält den Garbage Collector auf. - Kompatibilität: Chrome 54+, Firefox 38+, Edge 79+, Safari 15.4+. In Node.js ab Version 18 global verfügbar, davor über
worker_threads.