Start · Sprachen · JavaScript · Referenz · WebTransport.createBidirectionalStream()

WebTransport.createBidirectionalStream()

Methode

Öffnet asynchron einen neuen bidirektionalen Stream über eine WebTransport-Verbindung und liefert ein Promise auf einen <code>WebTransportBidirectionalStream</code>.

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

Signatur

WebTransport.prototype.createBidirectionalStream(options)

Beschreibung

Die Methode createBidirectionalStream() des WebTransport-Interfaces öffnet einen neuen, vom Client gestarteten Stream, über den in beide Richtungen Daten übertragen werden können. Das Promise wird mit einem WebTransportBidirectionalStream erfüllt. Dieser enthält einen readable-Stream (WebTransportReceiveStream) für Daten vom Server und einen writable-Stream (WebTransportSendStream) für Daten zum Server.

Bidirektionale Streams eignen sich für Anfrage/Antwort-Muster wie RPC-Aufrufe, Chat-Sitzungen oder Befehle, auf die der Server antwortet. Die Übertragung ist zuverlässig und geordnet, genau wie bei TCP. Weil jeder Stream aber ein eigener QUIC-Stream ist, gibt es zwischen verschiedenen Streams kein Head-of-Line-Blocking. Für unzuverlässige Übertragungen mit geringer Latenz nutzt man stattdessen WebTransport.datagrams, für Daten in nur eine Richtung createUnidirectionalStream().

Vor dem Aufruf sollte await transport.ready abgewartet werden. Die übertragenen Daten sind immer Bytes (Uint8Array). Text muss daher mit TextEncoder/TextDecoder bzw. TextEncoderStream/TextDecoderStream umgewandelt werden.

Parameter

Name Typ Default Beschreibung
$options Object {} Optionales Konfigurationsobjekt.
$options.sendOrder number 0 Priorität des Sende-Streams. Streams mit höherem Wert werden beim Senden bevorzugt. Der Wert kann später über writable.sendOrder geändert werden.
$options.sendGroup WebTransportSendGroup null Sendegruppe, erzeugt mit transport.createSendGroup(). Die Priorisierung über sendOrder gilt dann innerhalb der Gruppe (noch nicht überall unterstützt).
$options.waitUntilAvailable boolean false Bei true wartet das Promise, bis der Server weitere Streams erlaubt (Flusskontrolle). Bei false wird es sofort abgelehnt, wenn das Stream-Limit erreicht ist.

Rückgabewert

Typ
Promise<WebTransportBidirectionalStream>
Beschreibung
Promise, das mit einem Objekt mit den Eigenschaften readable (WebTransportReceiveStream) und writable (WebTransportSendStream) erfüllt wird. Es wird mit InvalidStateError abgelehnt, wenn die Verbindung geschlossen ist oder gerade geschlossen wird.

Beispiele

Stream öffnen, Nachricht senden und Antwort lesen

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

const stream = await transport.createBidirectionalStream();

// Senden
const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode('Hallo Server'));
await writer.close(); // Senderichtung beenden (FIN)

// Antwort lesen
const reader = stream.readable.getReader();
const decoder = new TextDecoder();
let antwort = '';
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  antwort += decoder.decode(value, { stream: true });
}
console.log('Antwort:', antwort);
Antwort: Hallo Server

RPC-Hilfsfunktion mit JSON und Text-Streams

const rpc = async (transport, method, params) => {
  const { readable, writable } = await transport.createBidirectionalStream({
    waitUntilAvailable: true
  });

  const writer = writable.getWriter();
  await writer.write(new TextEncoder().encode(JSON.stringify({ method, params })));
  await writer.close();

  let text = '';
  for await (const chunk of readable.pipeThrough(new TextDecoderStream())) {
    text += chunk;
  }
  return JSON.parse(text);
};

const transport = new WebTransport('https://api.example.com:4433/rpc');
await transport.ready;
const user = await rpc(transport, 'getUser', { id: 42 });
console.log(user.name);
Ada

Priorisierte Streams und Fehlerbehandlung

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

try {
  // Steuerbefehle bevorzugt senden
  const control = await transport.createBidirectionalStream({ sendOrder: 10 });
  const bulk = await transport.createBidirectionalStream({ sendOrder: 0 });

  const cw = control.writable.getWriter();
  await cw.write(Uint8Array.of(0x01)); // z. B. "Ping"

  // Stream bei Bedarf abbrechen
  await bulk.writable.abort();
  await bulk.readable.cancel();
} catch (err) {
  if (err.name === 'InvalidStateError') {
    console.error('Verbindung ist bereits geschlossen');
  } else {
    console.error('Stream-Fehler:', err);
  }
}

// Wichtig · Fallstricke

  • Kompatibilität: Wird in Chromium-Browsern und Firefox unterstützt, in Safari erst in neueren Versionen. Die Unterstützung vorher mit 'WebTransport' in globalThis prüfen. Funktioniert nur in sicheren Kontexten (HTTPS). Außerdem braucht der Server HTTP/3 mit WebTransport-Unterstützung.
  • Immer zuerst await transport.ready abwarten. Ist die Verbindung geschlossen, wird das Promise mit InvalidStateError abgelehnt.
  • Streams übertragen nur Bytes. Nachrichtengrenzen bleiben nicht erhalten: Ein write() kann beim Empfänger in mehreren read()-Teilen ankommen oder mit anderen zusammengefasst werden. Deshalb braucht man ein eigenes Framing (z. B. ein Längenpräfix) oder schließt den Stream pro Nachricht.
  • Den Writer mit close() schließen, sonst erfährt der Server nicht, dass keine Daten mehr kommen. Nicht mehr benötigte Streams mit abort()/cancel() freigeben, denn der Server begrenzt die Zahl gleichzeitiger Streams (Flusskontrolle).
  • Die Optionen sendGroup und waitUntilAvailable werden noch nicht überall unterstützt.
  • Vom Server gestartete bidirektionale Streams erhält man nicht über diese Methode, sondern über transport.incomingBidirectionalStreams.