Signatur
Beschreibung
Die Schnittstelle WebSocket öffnet eine Vollduplex-Verbindung zwischen Browser und Server. Anders als bei fetch() bleibt die Verbindung nach dem Handshake offen. Beide Seiten können jederzeit Nachrichten senden, ohne dass jedes Mal eine neue HTTP-Anfrage nötig ist. Typische Anwendungen sind Chats, Live-Dashboards, Mehrspieler-Spiele, Börsenkurse oder kollaboratives Bearbeiten.
Eine Verbindung entsteht mit new WebSocket(url, protocols). Der Aufbau läuft asynchron: Erst wenn das Ereignis open ausgelöst wurde, ist readyState gleich WebSocket.OPEN und send() kann genutzt werden. Eingehende Daten kommen über das Ereignis message an. Fehler meldet error, das Ende der Verbindung meldet close (mit code, reason und wasClean).
Wichtige Mitglieder:
- Methoden:
send(data)sendet einen String, einBlob, einenArrayBufferoder eineArrayBufferView.close(code, reason)beendet die Verbindung sauber. - Eigenschaften:
readyState(0 =CONNECTING, 1 =OPEN, 2 =CLOSING, 3 =CLOSED),bufferedAmount,binaryType("blob"oder"arraybuffer"),protocol,extensionsundurl. - Ereignisse:
open,message,errorundclose. Sie lassen sich peraddEventListener()oder überonopen,onmessage,onerrorundoncloseabonnieren.
Das Protokoll selbst hat keine automatische Wiederverbindung, keine Bestätigungen und keine Gegendruck-Steuerung (Backpressure). Solche Funktionen muss die Anwendung selbst bauen, etwa eine Wiederverbindung mit exponentiellem Backoff oder Heartbeats.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $url Pflicht | string | URL | Adresse des WebSocket-Servers mit dem Schema ws: oder wss:. Neuere Browser akzeptieren auch http:/https: und relative URLs und wandeln sie passend um. |
|
| $protocols | string | string[] | [] | Ein oder mehrere Unterprotokolle (z. B. "graphql-ws"). Der Server wählt eines aus, das danach in ws.protocol steht. |
Rückgabewert
WebSocket-Instanz im Zustand CONNECTING. Bei einer ungültigen URL wirft der Konstruktor sofort einen SyntaxError (DOMException).Beispiele
Verbindung öffnen, senden und empfangen
const ws = new WebSocket('wss://echo.websocket.org');
ws.addEventListener('open', () => {
console.log('Verbunden, readyState =', ws.readyState);
ws.send(JSON.stringify({ type: 'hallo', text: 'Servus Server!' }));
});
ws.addEventListener('message', (event) => {
console.log('Empfangen:', event.data);
});
ws.addEventListener('error', () => {
console.error('WebSocket-Fehler');
});
ws.addEventListener('close', (event) => {
console.log(`Geschlossen: code=${event.code}, sauber=${event.wasClean}`);
});
Binärdaten mit ArrayBuffer austauschen
const ws = new WebSocket('wss://echo.websocket.org');
ws.binaryType = 'arraybuffer'; // statt Standard 'blob'
ws.onopen = () => {
const bytes = new Uint8Array([1, 2, 3, 250]);
ws.send(bytes);
};
ws.onmessage = ({ data }) => {
if (data instanceof ArrayBuffer) {
console.log('Bytes:', Array.from(new Uint8Array(data)));
ws.close(1000, 'Fertig');
}
};
Automatische Wiederverbindung mit exponentiellem Backoff
const connect = (url, onMessage, attempt = 0) => {
const ws = new WebSocket(url);
ws.onopen = () => {
console.log('Verbunden');
attempt = 0; // Zähler nach Erfolg zurücksetzen
};
ws.onmessage = (e) => onMessage(e.data);
ws.onclose = (e) => {
if (e.code === 1000) return; // absichtlich geschlossen
const delay = Math.min(30000, 1000 * 2 ** attempt);
console.log(`Neuer Versuch in ${delay} ms`);
setTimeout(() => connect(url, onMessage, attempt + 1), delay);
};
return ws;
};
connect('wss://example.com/live', (data) => console.log('Update:', data));
Nur senden, wenn offen – mit Gegendruck-Prüfung
const safeSend = (ws, payload) => {
if (ws.readyState !== WebSocket.OPEN) {
console.warn('Nicht verbunden, Nachricht verworfen');
return false;
}
// Puffer zu voll? Dann lieber warten
if (ws.bufferedAmount > 1_000_000) {
console.warn('Sendepuffer voll:', ws.bufferedAmount, 'Bytes');
return false;
}
ws.send(typeof payload === 'string' ? payload : JSON.stringify(payload));
return true;
};
const ws = new WebSocket('wss://echo.websocket.org');
console.log(safeSend(ws, { ping: Date.now() }));
// Wichtig · Fallstricke
send()voropen: Ein Aufruf im ZustandCONNECTINGwirft einenInvalidStateError. Nach dem Schließen verwirft der Browser die Daten stillschweigend. Prüfe deshalb vorher immerreadyState.- Fehlerdetails: Das Ereignis
errorenthält aus Sicherheitsgründen keine Ursache. Hinweise liefert nur dercodeim folgendenclose-Ereignis, z. B.1006für einen abnormalen Abbruch. close(code): Erlaubt sind nur1000oder Werte von3000bis4999. Andere Werte werfen einenInvalidAccessError. Derreasondarf höchstens 123 Byte (UTF-8) lang sein.- Sicherheit: Nutze in Produktion immer
wss://, denn auf HTTPS-Seiten blockiert der Browserws://als Mixed Content. WebSockets unterliegen nicht der Same-Origin-Policy und nicht CORS. Der Server muss deshalb den HeaderOriginselbst prüfen, sonst droht Cross-Site WebSocket Hijacking. Eigene Header wieAuthorizationlassen sich nicht setzen. Zur Anmeldung dienen Cookies, ein Token in der ersten Nachricht oder ein kurzlebiges Token in der URL (Vorsicht: URLs landen in Logs). Empfangene Daten sind nicht vertrauenswürdig: keininnerHTMLmit Serverdaten,JSON.parseintry/catchkapseln. - Gegendruck:
send()blockiert nie. Bei großen Datenmengen wächstbufferedAmountohne Grenze. Neuere Alternativen mit Gegendruck-Steuerung sindWebSocketStream(experimentell, nur Chromium) undWebTransport. - Verbindungsabbrüche: Proxys und mobile Netze trennen inaktive Verbindungen oft stillschweigend. Regelmäßige Ping-Nachrichten auf Anwendungsebene helfen, denn die Browser-API gibt keinen Zugriff auf Ping-/Pong-Frames.
- Kompatibilität: Wird in allen modernen Browsern unterstützt. In Node.js ist
WebSocketab Version 22 global als Client verfügbar, davor braucht man z. B. das Paketws. Einen Server bietet die Browser-API nicht.