Start · Sprachen · JavaScript · Referenz · RTCDataChannel: open

RTCDataChannel: open

Ereignis

Wird ausgelöst, sobald der zugrunde liegende Transport eines <code>RTCDataChannel</code> geöffnet ist und Nachrichten gesendet und empfangen werden können.

seit JavaScript Baseline: alle modernen Browser (Chrome, Firefox, Kategorie: webapi

Signatur

dataChannel.addEventListener("open", handler)

Beschreibung

Das open-Ereignis wird an einem RTCDataChannel ausgelöst, sobald dessen Transport (SCTP über DTLS) aufgebaut ist und der Kanal Daten übertragen kann. Zu diesem Zeitpunkt wechselt readyState von "connecting" auf "open". Erst ab jetzt darf send() aufgerufen werden. Ein früherer Aufruf wirft einen InvalidStateError.

Einen Handler registriert man entweder mit addEventListener("open", handler) oder über die Eigenschaft onopen. Das übergebene Objekt ist ein einfaches Event und enthält keine zusätzlichen Daten. event.target verweist auf den geöffneten Kanal.

Typische Einsatzzwecke:

  • Die Oberfläche freischalten, zum Beispiel ein Chat-Eingabefeld.
  • Zwischengespeicherte Nachrichten aus einer Warteschlange senden.
  • Einen Begrüßungs- oder Handshake-Nachricht auf Anwendungsebene schicken.

Das Ereignis tritt sowohl auf der Seite auf, die den Kanal mit createDataChannel() erzeugt, als auch auf der Gegenseite, die den Kanal über das datachannel-Ereignis der RTCPeerConnection erhält. Bei ausgehandelten Kanälen (negotiated: true) wird es auf beiden Seiten ausgelöst.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignistyp, hier immer "open".
$handler Pflicht (event: Event) => void Callback, der beim Öffnen des Kanals aufgerufen wird. event.target ist der RTCDataChannel.
$options boolean | AddEventListenerOptions false Optionen wie bei addEventListener, zum Beispiel { once: true } oder { signal }.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt keinen Wert zurück. Der Handler erhält ein Event-Objekt ohne zusätzliche Eigenschaften.

Beispiele

Kanal erzeugen und beim Öffnen senden (addEventListener)

const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('chat');

channel.addEventListener('open', (event) => {
  console.log('Kanal offen:', event.target.label, event.target.readyState);
  channel.send('Hallo Gegenstelle!');
});

channel.addEventListener('message', (e) => console.log('Empfangen:', e.data));
// ... anschließend Signalisierung (Angebot/Antwort, ICE) durchführen
Kanal offen: chat open

Gegenseite: onopen am empfangenen Kanal

const pc = new RTCPeerConnection();

pc.ondatachannel = ({ channel }) => {
  channel.onopen = () => {
    console.log(`Kanal "${channel.label}" bereit`);
    document.querySelector('#send').disabled = false;
  };
  channel.onclose = () => {
    document.querySelector('#send').disabled = true;
  };
};
Kanal "chat" bereit

Nachrichten-Warteschlange bis zum Öffnen puffern

const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('sync');
const queue = [];

const sendSafe = (msg) => {
  if (channel.readyState === 'open') {
    channel.send(msg);
  } else {
    queue.push(msg);
  }
};

channel.addEventListener('open', () => {
  while (queue.length) channel.send(queue.shift());
  console.log('Warteschlange geleert');
}, { once: true });

sendSafe(JSON.stringify({ type: 'hello' }));
Warteschlange geleert

Auf das Öffnen per Promise warten und Listener entfernen

const waitForOpen = (channel, timeoutMs = 10000) =>
  new Promise((resolve, reject) => {
    if (channel.readyState === 'open') return resolve(channel);
    const onOpen = () => { cleanup(); resolve(channel); };
    const timer = setTimeout(() => { cleanup(); reject(new Error('Timeout')); }, timeoutMs);
    const cleanup = () => {
      clearTimeout(timer);
      channel.removeEventListener('open', onOpen);
    };
    channel.addEventListener('open', onOpen);
  });

const pc = new RTCPeerConnection();
const ch = pc.createDataChannel('files');
waitForOpen(ch)
  .then(() => ch.send('bereit'))
  .catch((err) => console.error(err.message));

// Wichtig · Fallstricke

  • Nicht zu früh senden: Rufen Sie send() vor dem open-Ereignis auf, also bei readyState === "connecting", wird ein InvalidStateError geworfen. Puffern Sie Nachrichten vorher oder prüfen Sie readyState.
  • Handler rechtzeitig registrieren: Beim empfangenen Kanal (datachannel-Ereignis) ist der Kanal manchmal schon offen, bevor der Handler gesetzt wird. Registrieren Sie den Handler deshalb sofort im datachannel-Handler und prüfen Sie zur Sicherheit zusätzlich readyState.
  • Signalisierung nötig: open wird nie ausgelöst, wenn der Austausch von Angebot und Antwort sowie der ICE-Kandidaten nicht abgeschlossen ist. Hinter restriktiven NATs ohne TURN-Server bleibt der Kanal auf connecting stehen, daher einen Timeout vorsehen.
  • Das Ereignis ist ein einfaches Event, es wird nicht durch den DOM propagiert (bubbles: false) und ist nicht abbrechbar.
  • Kompatibilität: Wird von allen aktuellen Browsern unterstützt. In Node.js gibt es keine eingebaute Unterstützung, dort sind Bibliotheken wie wrtc oder node-datachannel nötig. WebRTC verlangt einen sicheren Kontext (HTTPS oder localhost).