Start · Sprachen · JavaScript · Referenz · WebTransport.incomingBidirectionalStreams

WebTransport.incomingBidirectionalStreams

Eigenschaft

Schreibgeschützter <code>ReadableStream</code>, der für jeden vom Server geöffneten bidirektionalen Stream ein <code>WebTransportBidirectionalStream</code>-Objekt liefert.

seit JavaScript Chrome/Edge 97+, Firefox 114+, Safari 26.4+ (nur s Kategorie: webapi

Signatur

WebTransport.incomingBidirectionalStreams

Beschreibung

Die schreibgeschützte Eigenschaft incomingBidirectionalStreams des WebTransport-Interfaces liefert einen ReadableStream. Jeder Chunk dieses Streams ist ein WebTransportBidirectionalStream, also ein Kanal, den der Server geöffnet hat. Jedes dieser Objekte hat einen readable-Teil (WebTransportReceiveStream) zum Lesen und einen writable-Teil (WebTransportSendStream) zum Schreiben.

Die Eigenschaft ist für Protokolle gedacht, bei denen der Server von sich aus Anfrage-Antwort-Austausche startet, z. B. Server-seitige RPC-Aufrufe, Push-Anfragen mit Bestätigung oder Multiplayer-Sitzungen mit eigenen Kanälen pro Spieler oder Objekt. Streams, die der Client selbst öffnen will, erzeugt man dagegen mit WebTransport.prototype.createBidirectionalStream().

In der Regel liest man den Stream in einer Schleife mit getReader() und read() aus, bis done den Wert true hat. Jeden eingehenden Stream verarbeitet man dann unabhängig und asynchron, damit ein langsamer Kanal die anderen nicht blockiert. Mit dem Lesen sollte man erst beginnen, wenn transport.ready erfüllt ist.

Rückgabewert

Typ
ReadableStream<WebTransportBidirectionalStream>
Beschreibung
Ein ReadableStream, dessen Chunks WebTransportBidirectionalStream-Objekte mit den Eigenschaften readable und writable sind.

Beispiele

Eingehende bidirektionale Streams annehmen

const transport = new WebTransport('https://example.com:4999/wt');
await transport.ready;

const reader = transport.incomingBidirectionalStreams.getReader();

while (true) {
  const { value: bidiStream, done } = await reader.read();
  if (done) {
    console.log('Keine weiteren Streams vom Server.');
    break;
  }
  // Jeden Stream getrennt verarbeiten, nicht mit await blockieren
  handleStream(bidiStream);
}

async function handleStream({ readable, writable }) {
  console.log('Neuer Stream vom Server geöffnet');
  // ... siehe nächstes Beispiel
}
Neuer Stream vom Server geöffnet ...

Server-Anfrage lesen und beantworten (Echo/RPC)

const decoder = new TextDecoder();
const encoder = new TextEncoder();

async function handleStream({ readable, writable }) {
  // Komplette Anfrage des Servers lesen
  let text = '';
  for await (const chunk of readable) {
    text += decoder.decode(chunk, { stream: true });
  }
  console.log('Anfrage:', text);

  // Antwort über denselben Stream zurückschicken
  const writer = writable.getWriter();
  await writer.write(encoder.encode(`ACK: ${text}`));
  await writer.close();
}
Anfrage: ping

Mit for await und Fehlerbehandlung

const transport = new WebTransport('https://example.com:4999/wt');

try {
  await transport.ready;
  for await (const stream of transport.incomingBidirectionalStreams) {
    handleStream(stream).catch((err) =>
      console.error('Fehler in Stream:', err)
    );
  }
} catch (err) {
  console.error('Verbindung fehlgeschlagen oder abgebrochen:', err);
} finally {
  const info = await transport.closed.catch(() => ({}));
  console.log('Transport geschlossen', info);
}
Transport geschlossen { closeCode: 0, reason: '' }

// Wichtig · Fallstricke

  • Browser-Unterstützung: WebTransport gibt es in Chromium-Browsern ab Version 97 und in Firefox ab Version 114. Safari unterstützt es erst ab Version 26.4. Die Eigenschaft ist nur in einem sicheren Kontext (HTTPS) und über HTTP/3 verfügbar. Vorher mit 'WebTransport' in globalThis prüfen.
  • Asynchrone Iteration: for await...of direkt auf einem ReadableStream funktioniert nicht in allen Browsern. Als Rückfallebene getReader() mit read() verwenden.
  • Nicht blockieren: Wenn man innerhalb der Leseschleife auf die Verarbeitung eines Streams wartet (await handleStream()), werden alle weiteren Streams verzögert. Stattdessen parallel verarbeiten.
  • Nur ein Reader: Solange ein Reader existiert, ist der Stream gesperrt (locked). Ein zweiter Aufruf von getReader() wirft einen TypeError.
  • Beim Schließen: Wird der Transport mit close() geschlossen, endet der Stream (done: true). Bei einem Verbindungsfehler wird er dagegen mit einem Fehler abgebrochen, deshalb immer try/catch nutzen.
  • Der Server bestimmt, wie viele Streams er gleichzeitig öffnet. Der Client sollte deshalb Grenzen setzen oder nicht benötigte Streams gezielt mit readable.cancel() bzw. writable.abort() beenden.