Start · Sprachen · JavaScript · Referenz · StorageAccessHandle.BroadcastChannel()

StorageAccessHandle.BroadcastChannel()

Methode

Erzeugt über ein <code>StorageAccessHandle</code> ein nicht partitioniertes <code>BroadcastChannel</code>-Objekt, das im Drittanbieter-Kontext mit Top-Level-Seiten derselben Herkunft kommuniziert.

seit JavaScript Chromium 125+ (experimentell, keine Baseline) Kategorie: webapi

Signatur

StorageAccessHandle.prototype.BroadcastChannel(name)

Beschreibung

Moderne Browser partitionieren Speicher und Kommunikationskanäle in Drittanbieter-Kontexten, z. B. in eingebetteten <iframe>s. Ein normaler new BroadcastChannel("x") in einem iframe von widget.example auf shop.example landet deshalb in einer anderen Partition als derselbe Kanal, wenn widget.example direkt als Hauptseite geöffnet ist. Die Nachrichten erreichen sich gegenseitig nicht.

Mit der erweiterten Storage Access API lässt sich das gezielt umgehen: document.requestStorageAccess({ BroadcastChannel: true }) liefert ein StorageAccessHandle. Dessen Methode BroadcastChannel(name) gibt einen nicht partitionierten Kanal zurück. Er verhält sich wie ein gewöhnlicher BroadcastChannel mit postMessage(), onmessage und close(). Er teilt sich den Nachrichtenraum aber mit allen Top-Level-Kontexten derselben Herkunft und mit anderen Frames, die ebenfalls nicht partitionierten Zugriff haben.

Typische Einsatzfälle sind eingebettete Widgets wie Chat, Login-Status oder Zahlungs-Iframes. Sie sollen den Zustand zwischen einem geöffneten Tab der eigenen Website und der eingebetteten Instanz abgleichen, etwa bei einem Abmelde-Ereignis oder einem Wechsel des Designs.

Die Methode wird ohne new aufgerufen. Sie funktioniert nur, wenn beim Anfordern des Zugriffs BroadcastChannel: true (oder all: true) angegeben wurde.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Name des Kanals. Alle nicht partitionierten Kanäle derselben Herkunft mit gleichem Namen empfangen die Nachrichten der anderen. Andere Werte werden in einen String umgewandelt.

Rückgabewert

Typ
BroadcastChannel
Beschreibung
Ein nicht partitioniertes BroadcastChannel-Objekt mit der üblichen Schnittstelle (postMessage(), close(), message- und messageerror-Ereignisse).

Beispiele

Nicht partitionierten Kanal im iframe anfordern

// Läuft im eingebetteten iframe von widget.example
const button = document.querySelector('#connect');

button.addEventListener('click', async () => {
  try {
    // Muss innerhalb einer Nutzeraktion aufgerufen werden
    const handle = await document.requestStorageAccess({ BroadcastChannel: true });
    const channel = handle.BroadcastChannel('session');

    channel.addEventListener('message', (event) => {
      console.log('Nachricht vom Haupt-Tab:', event.data);
    });

    channel.postMessage({ type: 'widget-ready' });
  } catch (err) {
    console.warn('Kein Speicherzugriff:', err.name);
  }
});
Nachricht vom Haupt-Tab: { type: 'logout' }

Gegenstück im Top-Level-Tab derselben Herkunft

// Läuft auf https://widget.example (Hauptseite, nicht eingebettet)
// Hier ist der normale BroadcastChannel bereits nicht partitioniert.
const channel = new BroadcastChannel('session');

channel.onmessage = (event) => {
  if (event.data.type === 'widget-ready') {
    console.log('Eingebettetes Widget ist verbunden');
  }
};

document.querySelector('#logout').addEventListener('click', () => {
  channel.postMessage({ type: 'logout' });
});
Eingebettetes Widget ist verbunden

Mit Feature-Erkennung und Rückfallebene

const getSessionChannel = async () => {
  const supportsHandle = 'requestStorageAccess' in document &&
    typeof StorageAccessHandle !== 'undefined' &&
    'BroadcastChannel' in StorageAccessHandle.prototype;

  if (supportsHandle) {
    try {
      const handle = await document.requestStorageAccess({ BroadcastChannel: true });
      return { channel: handle.BroadcastChannel('session'), partitioned: false };
    } catch {
      // Zugriff verweigert, weiter mit Rückfallebene
    }
  }
  // Rückfall: partitionierter Kanal, der nur innerhalb derselben Partition wirkt
  return { channel: new BroadcastChannel('session'), partitioned: true };
};

const { channel, partitioned } = await getSessionChannel();
console.log('Partitioniert:', partitioned);
// Später aufräumen
window.addEventListener('pagehide', () => channel.close());
Partitioniert: false

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die Methode wird derzeit nur von Chromium-basierten Browsern unterstützt (ab Version 125). Firefox und Safari kennen StorageAccessHandle nicht. Prüfe die Unterstützung daher immer vorher und sieh eine Rückfallebene vor.
  • Nicht angeforderter Typ: Wurde requestStorageAccess() ohne BroadcastChannel: true bzw. all: true aufgerufen, wirft die Methode eine DOMException, laut Spezifikation einen SecurityError.
  • Nutzeraktion nötig: requestStorageAccess() braucht in der Regel eine Nutzeraktion, etwa einen Klick. Der Browser kann den Zugriff je nach seinen Heuristiken, der Berechtigung oder Nutzereinstellungen auch verweigern.
  • Kein new: Der Aufruf lautet handle.BroadcastChannel('name'). Die Schreibweise mit großem Anfangsbuchstaben ist trotzdem ein normaler Methodenaufruf.
  • Sicherheit: Ein nicht partitionierter Kanal hebt eine Datenschutzgrenze auf. Übertrage keine sensiblen Daten ungeprüft. Prüfe in message-Handlern Struktur und Typ von event.data, denn jeder Kontext derselben Herkunft kann Nachrichten senden.
  • Rufe close() auf, sobald der Kanal nicht mehr gebraucht wird. So wird der Speicher freigegeben und der Back/Forward-Cache nicht blockiert.