Signatur
Beschreibung
WebSocketStream ist eine Alternative zum ereignisbasierten WebSocket-Interface. Statt mit onmessage, onopen und onclose arbeitet man mit Promises und der Streams-API. Das Objekt entsteht mit new WebSocketStream(url, options). Sobald die Verbindung steht, wird das Promise opened erfüllt. Es liefert ein Objekt mit readable (ein ReadableStream mit eingehenden Nachrichten), writable (ein WritableStream zum Senden) sowie protocol und extensions.
Der größte Vorteil ist der eingebaute Gegendruck (Backpressure). Beim klassischen WebSocket können sich eingehende Nachrichten im Speicher stauen, wenn die Anwendung sie nicht schnell genug verarbeitet. Beim WebSocketStream liest man dagegen nur, wenn man bereit ist. Der Browser bremst dann den Empfang, sodass der Puffer nicht unbegrenzt wächst. Beim Senden funktioniert das genauso: await writer.write() wartet, bis wieder Platz ist.
Weitere Mitglieder:
url: die aufgelöste URL der Verbindung (nur lesbar).opened:Promise<{ readable, writable, protocol, extensions }>.closed:Promise<{ closeCode, reason }>. Es wird beim sauberen Schließen erfüllt und bei einem Verbindungsfehler abgelehnt.close({ closeCode, reason }): schließt die Verbindung.
Die Schnittstelle eignet sich besonders für Anwendungen mit hohem Datenaufkommen, etwa Live-Telemetrie, Datei-Übertragung oder Chat mit vielen Nachrichten. Außerdem passt sie gut zu Stream-Verkettungen mit pipeTo() und pipeThrough().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $url Pflicht | string | URL | URL des WebSocket-Servers, üblicherweise mit dem Schema wss:// oder ws://. Relative URLs und http(s):// werden in aktuellen Implementierungen passend umgewandelt. |
|
| $options | object | {} | Optionales Konfigurationsobjekt für den Konstruktor. |
| $options.protocols | string[] | [] | Liste von Unterprotokollen, die dem Server angeboten werden. Das ausgehandelte Protokoll steht danach in opened.protocol. |
| $options.signal | AbortSignal | Ein AbortSignal, mit dem man den Verbindungsaufbau abbrechen kann, bevor der Handshake abgeschlossen ist, zum Beispiel für einen Timeout. Danach hat das Signal keine Wirkung mehr. |
Rückgabewert
WebSocketStream-Instanz. Die Verbindung wird sofort aufgebaut. Ob sie zustande kommt, zeigt das Promise opened.Beispiele
Verbinden, senden und Nachrichten lesen
const wss = new WebSocketStream('wss://echo.websocket.org');
const { readable, writable, protocol } = await wss.opened;
console.log('Verbunden, Protokoll:', protocol || '(keins)');
const writer = writable.getWriter();
const reader = readable.getReader();
// Nachricht senden – await berücksichtigt den Gegendruck
await writer.write('Hallo Server!');
// Nachrichten lesen, bis der Server die Verbindung schließt
while (true) {
const { value, done } = await reader.read();
if (done) break;
// value ist ein String (Text) oder ein ArrayBuffer (Binärdaten)
console.log('Empfangen:', value);
if (value === 'Hallo Server!') break;
}
wss.close({ closeCode: 1000, reason: 'Fertig' });
const { closeCode, reason } = await wss.closed;
console.log('Geschlossen:', closeCode, reason);
Verbindungsaufbau mit Timeout über AbortSignal
const connect = async (url, timeoutMs = 5000) => {
const wss = new WebSocketStream(url, {
protocols: ['chat.v1'],
signal: AbortSignal.timeout(timeoutMs),
});
try {
const conn = await wss.opened;
return { wss, ...conn };
} catch (err) {
console.error('Verbindung fehlgeschlagen:', err.name);
throw err;
}
};
const { wss, protocol } = await connect('wss://example.com/chat');
console.log('Ausgehandeltes Protokoll:', protocol);
Eingehende JSON-Nachrichten per pipeThrough verarbeiten
const wss = new WebSocketStream('wss://example.com/telemetry');
const { readable } = await wss.opened;
// Nachrichten in Objekte umwandeln
const parseJson = new TransformStream({
transform(chunk, controller) {
if (typeof chunk === 'string') controller.enqueue(JSON.parse(chunk));
},
});
// Langsame Verarbeitung: der Browser bremst den Empfang automatisch
await readable.pipeThrough(parseJson).pipeTo(new WritableStream({
async write(data) {
console.log('Messwert:', data.value);
await new Promise((r) => setTimeout(r, 100));
},
}));
Feature-Erkennung mit Rückfall auf WebSocket
const url = 'wss://example.com/socket';
if ('WebSocketStream' in globalThis) {
const wss = new WebSocketStream(url);
wss.closed
.then(({ closeCode }) => console.log('Sauber geschlossen:', closeCode))
.catch((err) => console.error('Verbindungsfehler:', err));
} else {
const ws = new WebSocket(url);
ws.addEventListener('message', (e) => console.log(e.data));
}