Start · Sprachen · JavaScript · Referenz · WebTransportReceiveStream

WebTransportReceiveStream

Schnittstelle

Ein <code>ReadableStream</code> aus Bytes, mit dem man eingehende unidirektionale Streams oder die Leseseite bidirektionaler WebTransport-Streams liest.

seit JavaScript Chrome/Edge 97+, Firefox 114+, Safari: noch nicht Kategorie: webapi

Signatur

interface WebTransportReceiveStream extends ReadableStream

Beschreibung

WebTransportReceiveStream ist die Leseseite eines WebTransport-Streams über HTTP/3 (QUIC). Objekte dieses Typs erzeugt man nicht selbst. Der Browser liefert sie auf zwei Wegen: als Einträge von WebTransport.incomingUnidirectionalStreams, wenn der Server einen unidirektionalen Stream öffnet, und als Eigenschaft readable eines WebTransportBidirectionalStream.

Weil das Interface von ReadableStream erbt, stehen alle bekannten Methoden der Streams-API zur Verfügung: getReader() (auch mit { mode: "byob" }, da es ein Byte-Stream ist), pipeTo(), pipeThrough(), tee(), cancel() und die asynchrone Iteration mit for await...of. Jeder gelesene Chunk ist ein Uint8Array.

Neu hinzu kommt nur die Methode getStats(). Sie gibt ein Promise auf ein Objekt mit Statistiken zum Stream zurück, zum Beispiel timestamp, bytesReceived und bytesRead. Damit lassen sich Durchsatz und Rückstau messen.

Typische Einsatzfälle sind Echtzeitanwendungen mit wenig Verzögerung: Spielzustände, Live-Medien, Telemetrie oder Server-Push von Ereignissen. Streams sind dabei zuverlässig und geordnet. Für unzuverlässige Nachrichten mit geringster Latenz gibt es stattdessen WebTransport.datagrams.

Rückgabewert

Typ
WebTransportReceiveStream
Beschreibung
Wird nicht per Konstruktor erzeugt, sondern von incomingUnidirectionalStreams bzw. WebTransportBidirectionalStream.readable geliefert. Methode getStats(): Promise<WebTransportReceiveStreamStats>.

Beispiele

Eingehende unidirektionale Streams des Servers lesen

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

const decoder = new TextDecoder();

// Jeder Eintrag ist ein WebTransportReceiveStream
for await (const stream of transport.incomingUnidirectionalStreams) {
  // Ohne await: mehrere Streams parallel verarbeiten
  (async () => {
    let text = '';
    for await (const chunk of stream) { // chunk: Uint8Array
      text += decoder.decode(chunk, { stream: true });
    }
    text += decoder.decode();
    console.log('Nachricht vom Server:', text);
  })();
}
Nachricht vom Server: {"type":"welcome"}

Antwort über einen bidirektionalen Stream lesen

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

const { readable, writable } = await transport.createBidirectionalStream();

// Anfrage senden
const writer = writable.getWriter();
await writer.write(new TextEncoder().encode('PING'));
await writer.close();

// readable ist ein WebTransportReceiveStream
const reader = readable.getReader();
const parts = [];
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  parts.push(value);
}
const antwort = new TextDecoder().decode(await new Blob(parts).arrayBuffer());
console.log(antwort);
PONG

Statistiken abfragen und Stream abbrechen

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

const reader = transport.incomingUnidirectionalStreams.getReader();
const { value: stream } = await reader.read();

const stats = await stream.getStats();
console.log(`Empfangen: ${stats.bytesReceived} B, gelesen: ${stats.bytesRead} B`);

// Nicht mehr benötigt: Stream abbrechen (sendet STOP_SENDING an den Server)
await stream.cancel('Nicht mehr benötigt');
Empfangen: 2048 B, gelesen: 0 B

// Wichtig · Fallstricke

  • Kompatibilität: Unterstützt in Chromium-Browsern (ab 97) und Firefox (ab 114). Safari unterstützt WebTransport noch nicht. Die API gibt es nur in sicheren Kontexten und in Web Workern. Ob sie vorhanden ist, prüft man mit 'WebTransport' in globalThis. getStats() ist noch nicht überall eingebaut.
  • Keine Nachrichtengrenzen: Die Chunks entsprechen nicht zwingend den Schreibaufrufen des Servers. Mehrere Nachrichten auf einem Stream müssen daher selbst eingerahmt werden, etwa mit einem Längenpräfix oder einem Trennzeichen.
  • Sperre (Lock): Solange ein Reader aktiv ist, ist der Stream gesperrt. Andere Konsumenten brauchen reader.releaseLock() oder tee().
  • Fehlerbehandlung: Bricht der Server den Stream ab (RESET_STREAM) oder wird die Verbindung geschlossen, lehnt read() mit einem WebTransportError ab. Dessen Eigenschaft streamErrorCode enthält den Fehlercode der Anwendung. Leseschleifen gehören deshalb immer in try/catch.
  • Rückstau: Wer nicht liest, bremst den Sender über die Flusskontrolle von QUIC aus. Nicht benötigte Streams sollte man mit cancel() abbrechen, damit sie keine Ressourcen blockieren.
  • Sicherheit: Empfangene Daten sind nicht vertrauenswürdig. Sie müssen geprüft werden, bevor sie etwa in das DOM eingefügt werden (XSS-Gefahr). Serverzertifikate kann man mit serverCertificateHashes festlegen. Das ist nur für kurzlebige, selbstsignierte Zertifikate gedacht.