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

WebTransport.createUnidirectionalStream()

Methode

Öffnet asynchron einen unidirektionalen Stream zum Server und liefert einen <code>WritableStream</code> (<code>WebTransportSendStream</code>), über den der Client nur senden kann.

seit JavaScript Chrome/Edge 97+, Firefox 114+, Safari erst in neue Kategorie: webapi

Signatur

WebTransport.prototype.createUnidirectionalStream(options)

Beschreibung

createUnidirectionalStream() öffnet über eine bestehende WebTransport-Verbindung (HTTP/3 bzw. QUIC) einen neuen unidirektionalen Stream. Nur der Client schreibt, der Server liest. Das zurückgegebene Promise wird mit einem WebTransportSendStream erfüllt. Dieser erbt von WritableStream, deshalb schreibt man die Daten wie gewohnt über einen WritableStreamDefaultWriter als Uint8Array.

Unidirektionale Streams sind zuverlässig und geordnet. Anders als bei Datagrammen kommen die Daten also vollständig und in der richtigen Reihenfolge an. Jeder Stream ist von den anderen unabhängig. Geht in einem Stream ein Paket verloren, bremst das die übrigen Streams nicht aus (kein Head-of-Line-Blocking). Deshalb passen sie gut für in sich abgeschlossene Nachrichten, zum Beispiel einzelne Spielzustände, Log-Einträge, Datei-Teile oder Telemetrie-Pakete, bei denen keine Antwort über denselben Stream nötig ist.

Über die Option sendOrder legst du fest, welcher Stream beim Senden bevorzugt wird. Streams mit höherem Wert werden zuerst bedient. Mit waitUntilAvailable bestimmst du, was passiert, wenn der Server gerade keine weiteren Streams zulässt (Flusskontrolle): Entweder wartet das Promise, bis wieder ein Stream frei ist, oder es wird sofort abgelehnt.

Die Methode darf erst aufgerufen werden, wenn die Verbindung steht. Warte also vorher auf transport.ready. Schließt du den Writer mit close(), erfährt der Server, dass der Stream zu Ende ist. Mit abort() brichst du den Stream mit einem Fehler ab.

Parameter

Name Typ Default Beschreibung
$options Object {} Optionales Konfigurationsobjekt mit den folgenden Eigenschaften.
$options.sendOrder number 0 Sendepriorität des Streams. Streams mit höherem Wert werden beim Senden bevorzugt, bei gleichem Wert teilen sie sich die Bandbreite. Lässt sich später über stream.sendOrder ändern.
$options.waitUntilAvailable boolean false Bei true wartet das Promise, bis der Server laut Flusskontrolle einen weiteren Stream erlaubt. Bei false wird es sofort abgelehnt, wenn gerade kein Stream verfügbar ist.
$options.sendGroup WebTransportSendGroup Optionale Sendegruppe, in der sendOrder relativ zu anderen Streams derselben Gruppe gilt. Neu im Standard und noch nicht überall umgesetzt.

Rückgabewert

Typ
Promise<WebTransportSendStream>
Beschreibung
Ein Promise, das mit einem WebTransportSendStream (Unterklasse von WritableStream) erfüllt wird. Es wird mit einem InvalidStateError abgelehnt, wenn die Verbindung geschlossen oder fehlgeschlagen ist. Ohne waitUntilAvailable wird es auch abgelehnt, wenn gerade kein Stream verfügbar ist.

Beispiele

Einfache Textnachricht über einen unidirektionalen Stream senden

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

const stream = await transport.createUnidirectionalStream();
const writer = stream.getWriter();

const encoder = new TextEncoder();
await writer.write(encoder.encode('Hallo Server!'));

// Stream sauber beenden – der Server erhält ein End-of-Stream
await writer.close();
console.log('Nachricht gesendet und Stream geschlossen');
Nachricht gesendet und Stream geschlossen

Eine Nachricht pro Stream – mit Priorität über sendOrder

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

const encoder = new TextEncoder();

// Jede Nachricht in einem eigenen Stream: kein Head-of-Line-Blocking
const sendMessage = async (payload, priority = 0) => {
  const stream = await transport.createUnidirectionalStream({
    sendOrder: priority,
    waitUntilAvailable: true
  });
  const writer = stream.getWriter();
  await writer.write(encoder.encode(JSON.stringify(payload)));
  await writer.close();
};

// Eingaben des Spielers haben Vorrang vor Telemetrie
await Promise.all([
  sendMessage({ type: 'telemetry', fps: 60 }, 0),
  sendMessage({ type: 'input', key: 'jump' }, 10)
]);
console.log('Alle Nachrichten übertragen');
Alle Nachrichten übertragen

Datei in Blöcken hochladen mit Fehlerbehandlung

const uploadFile = async (transport, file) => {
  let writer;
  try {
    const stream = await transport.createUnidirectionalStream();
    writer = stream.getWriter();

    // Datei-Stream direkt in Blöcken lesen und senden
    const reader = file.stream().getReader();
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      await writer.ready; // Gegendruck beachten
      await writer.write(value);
    }
    await writer.close();
    console.log(`${file.name} hochgeladen`);
  } catch (err) {
    console.error('Upload fehlgeschlagen:', err.name, err.message);
    await writer?.abort(err).catch(() => {});
  }
};

const transport = new WebTransport('https://upload.example.com/wt');
await transport.ready;
const input = document.querySelector('input[type=file]');
input.addEventListener('change', () => uploadFile(transport, input.files[0]));
bericht.pdf hochgeladen

// Wichtig · Fallstricke

  • Erst auf transport.ready warten: Rufst du die Methode vor dem Verbindungsaufbau auf, wartet sie in der Regel. Scheitert die Verbindung, wird das Promise abgelehnt. Nach transport.close() oder einem Verbindungsfehler gibt es einen InvalidStateError.
  • Nur Binärdaten: write() nimmt ArrayBuffer/Uint8Array an. Strings musst du vorher mit TextEncoder umwandeln.
  • Keine Nachrichtengrenzen innerhalb eines Streams: Mehrere write()-Aufrufe kommen beim Server als Bytestrom an. Schickst du mehrere Nachrichten über einen Stream, brauchst du eine eigene Rahmung (z. B. Längenpräfix). Alternativ nutzt du einen Stream pro Nachricht.
  • Stream-Limits: Der Server begrenzt, wie viele Streams gleichzeitig offen sein dürfen. Mit waitUntilAvailable: true wartest du auf einen freien Platz, statt einen Fehler zu bekommen. Schließe Streams immer mit close() oder abort().
  • Voraussetzungen: Die Methode gibt es nur in sicheren Kontexten (HTTPS). Der Server muss HTTP/3 mit WebTransport unterstützen. Selbstsignierte Zertifikate gehen nur mit serverCertificateHashes im Konstruktor.
  • Kompatibilität: Chromium-Browser ab Version 97 und Firefox ab 114 unterstützen die Methode, Safari erst in neueren Versionen. sendOrder und sendGroup sind nicht überall umgesetzt. Prüfe die Unterstützung mit 'WebTransport' in globalThis und halte einen Ersatz bereit (z. B. WebSocket).