Signatur
Beschreibung
WebTransportDatagramsWritable gehört zur WebTransport-API. Das Interface erweitert WritableStream. Jeder Aufruf von writer.write(chunk) mit einem Uint8Array (oder einer anderen BufferSource) sendet genau ein Datagramm über die HTTP/3-Verbindung (QUIC) zum Server.
Datagramme sind unzuverlässig und ungeordnet. Sie können verloren gehen, doppelt oder in anderer Reihenfolge ankommen. Dafür haben sie eine sehr geringe Latenz. Deshalb passen sie gut zu Daten, bei denen nur der neueste Stand zählt, zum Beispiel:
- Spielerpositionen in Echtzeitspielen,
- Sensor- und Telemetriewerte,
- Steuerbefehle mit kurzer Lebensdauer.
Wenn jede Nachricht ankommen muss, nimmt man stattdessen Streams (createBidirectionalStream() bzw. createUnidirectionalStream()).
Instanzen entstehen über transport.datagrams.createWritable(options). Man kann mehrere solcher Streams anlegen und ihnen unterschiedliche Prioritäten geben. Dafür gibt es zwei Eigenschaften, die man auch nachträglich setzen kann:
sendOrder: Zahl für die Sendepriorität. Höhere Werte werden zuerst gesendet.sendGroup: ordnet den Stream einerWebTransportSendGroupzu. Innerhalb einer Gruppe wird nachsendOrderpriorisiert.
In älteren Implementierungen ist transport.datagrams.writable ein einfacher WritableStream ohne diese Eigenschaften.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options | object | {} | Optionen für WebTransportDatagramDuplexStream.createWritable(options), womit Instanzen dieses Interfaces erzeugt werden. |
| $options.sendGroup | WebTransportSendGroup | null | null | Sendegruppe, zu der der Stream gehört. Die Gruppe erzeugt man mit transport.createSendGroup(). Später lesbar und änderbar über die Eigenschaft sendGroup. |
| $options.sendOrder | number | 0 | Sendepriorität. Höhere Werte werden bevorzugt gesendet. Später lesbar und änderbar über die Eigenschaft sendOrder. |
Rückgabewert
createWritable() gibt einen beschreibbaren Stream zurück. Mit getWriter() holt man sich einen WritableStreamDefaultWriter; jeder write()-Aufruf sendet ein Datagramm.Beispiele
Stream anlegen und ein Datagramm senden
const transport = new WebTransport('https://example.com:4999/wt');
await transport.ready;
// Beschreibbaren Datagramm-Stream erzeugen
const writable = transport.datagrams.createWritable();
const writer = writable.getWriter();
const data = new TextEncoder().encode('ping');
await writer.write(data);
console.log('Datagramm gesendet, Größe:', data.byteLength);
writer.releaseLock();
Echtzeit-Positionen mit hoher Priorität senden
const transport = new WebTransport('https://game.example.com/wt');
await transport.ready;
// Positionen dringend, Chat-Hinweise weniger dringend
const positions = transport.datagrams.createWritable({ sendOrder: 10 });
const hints = transport.datagrams.createWritable({ sendOrder: 1 });
const posWriter = positions.getWriter();
const sendPosition = async (x, y) => {
const buf = new Float32Array([x, y]);
await posWriter.ready; // Gegendruck (Backpressure) beachten
posWriter.write(new Uint8Array(buf.buffer));
};
await sendPosition(12.5, 7.25);
console.log(positions.sendOrder, hints.sendOrder);
Sendegruppe und Priorität nachträglich ändern
const transport = new WebTransport('https://example.com/wt');
await transport.ready;
const group = transport.createSendGroup();
const writable = transport.datagrams.createWritable({ sendGroup: group });
// Priorität zur Laufzeit anheben
writable.sendOrder = 5;
console.log(writable.sendGroup === group, writable.sendOrder);
Maximale Datagrammgröße prüfen und Fehler behandeln
const transport = new WebTransport('https://example.com/wt');
await transport.ready;
const max = transport.datagrams.maxDatagramSize;
const writer = transport.datagrams.createWritable().getWriter();
const payload = new Uint8Array(2000);
if (payload.byteLength > max) {
console.warn(`Zu groß (${payload.byteLength} > ${max}), wird aufgeteilt`);
for (let i = 0; i < payload.byteLength; i += max) {
await writer.write(payload.subarray(i, i + max));
}
} else {
await writer.write(payload);
}
transport.closed.catch((err) => console.error('Verbindung beendet:', err));
// Wichtig · Fallstricke
- Keine Zustellgarantie: Wenn
write()erfüllt wird, heißt das nur, dass das Datagramm lokal angenommen wurde. Ob es ankommt, ist damit nicht gesagt. Datagramme können still verworfen werden, etwa wenn sie länger in der Warteschlange liegen alsdatagrams.outgoingMaxAgeerlaubt. - Größenlimit: Ein Datagramm darf nicht größer sein als
transport.datagrams.maxDatagramSize(oft etwa 1200 Byte, abhängig vom Pfad). Zu große Daten werden verworfen und nicht automatisch aufgeteilt. Das Aufteilen und Zusammensetzen muss die Anwendung selbst übernehmen. - Gegendruck (Backpressure): Vor dem Schreiben auf
writer.readywarten. Sonst wächst die interne Warteschlange (outgoingHighWaterMark) und Daten veralten. - Kompatibilität: WebTransport gibt es nur im sicheren Kontext (HTTPS) und nur mit einem HTTP/3-Server.
createWritable(),sendOrderundsendGroupsind neuer als die Basis-API. Ältere Browser bieten nurdatagrams.writableals einfachenWritableStream. Safari unterstützt WebTransport bislang nicht. Deshalb vorher prüfen, ob die Funktion vorhanden ist, z. B. mit'createWritable' in transport.datagrams. - Es kann immer nur ein Writer den Stream sperren. Mit
releaseLock()gibt man ihn wieder frei. Wird die Verbindung geschlossen, schlagen alle weiterenwrite()-Aufrufe fehl.