Signatur
Beschreibung
Der Konstruktor SharedWorker() startet einen geteilten Worker, also einen Hintergrund-Thread, auf den mehrere Browsing-Kontexte (Tabs, Fenster, iframes, auch andere Worker) mit demselben Ursprung zugreifen. Existiert schon ein SharedWorker mit gleicher Skript-URL und gleichem name, legt der Browser keinen neuen Worker an. Stattdessen verbindet er den Aufrufer mit der laufenden Instanz.
Die Kommunikation läuft immer über einen MessagePort, den du als worker.port erreichst. Im Worker-Skript meldet das Ereignis connect jede neue Verbindung. Den zugehörigen Port findest du in event.ports[0]. Typische Einsatzfälle sind eine einzige WebSocket-Verbindung für alle Tabs, ein gemeinsamer Zwischenspeicher, Status-Synchronisierung zwischen Tabs oder das Bündeln teurer Berechnungen.
Der Worker bleibt aktiv, solange noch mindestens ein verbundener Kontext existiert. Wird der letzte Tab geschlossen, beendet der Browser den Worker. Mit der Option type: "module" kannst du ES-Module samt import im Worker verwenden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $url Pflicht | string | URL | URL des Worker-Skripts. Das Skript muss dem Same-Origin-Prinzip genügen. Relative URLs werden relativ zur Basis-URL des Dokuments aufgelöst. | |
| $options | string | { name?: string, type?: "classic" | "module", credentials?: "omit" | "same-origin" | "include" } | { type: "classic", credentials: "same-origin" } | Als Zeichenkette ist das der Name des Workers (ältere Kurzform). Als Objekt:
|
Rückgabewert
SharedWorker-Objekt. Die Eigenschaft port (MessagePort) dient zur Kommunikation. Das Ereignis error wird ausgelöst, wenn das Skript nicht geladen werden kann.Beispiele
Einfacher geteilter Zähler über mehrere Tabs
// main.js – in jedem Tab eingebunden
const worker = new SharedWorker('/counter-worker.js');
worker.port.onmessage = (event) => {
console.log(`Verbundene Tabs: ${event.data}`);
};
// onmessage startet den Port implizit; bei addEventListener wäre port.start() nötig
worker.port.postMessage('hallo');
// counter-worker.js
const ports = [];
self.addEventListener('connect', (event) => {
const port = event.ports[0];
ports.push(port);
port.onmessage = () => {
// allen verbundenen Tabs die aktuelle Anzahl mitteilen
ports.forEach((p) => p.postMessage(ports.length));
};
});
Modul-Worker mit Namen und Fehlerbehandlung
if ('SharedWorker' in window) {
const worker = new SharedWorker(new URL('./sync-worker.js', import.meta.url), {
type: 'module',
name: 'app-sync'
});
worker.addEventListener('error', (e) => {
console.error('SharedWorker konnte nicht geladen werden:', e.message);
});
worker.port.addEventListener('message', ({ data }) => {
console.log('Status:', data);
});
worker.port.start(); // Pflicht bei addEventListener
worker.port.postMessage({ type: 'subscribe', topic: 'news' });
} else {
console.warn('SharedWorker nicht unterstützt – Fallback auf BroadcastChannel');
}
Eine WebSocket-Verbindung für alle Tabs
// ws-worker.js
const ports = new Set();
const socket = new WebSocket('wss://example.com/live');
socket.addEventListener('message', (e) => {
// eingehende Nachricht an alle Tabs weiterreichen
for (const port of ports) port.postMessage(e.data);
});
self.onconnect = ({ ports: [port] }) => {
ports.add(port);
port.onmessage = ({ data }) => {
if (data === 'close') ports.delete(port);
else if (socket.readyState === WebSocket.OPEN) socket.send(data);
};
};
// main.js
const ws = new SharedWorker('/ws-worker.js', 'live-socket');
ws.port.onmessage = ({ data }) => console.log('Live:', data);
window.addEventListener('pagehide', () => ws.port.postMessage('close'));
// Wichtig · Fallstricke
- Browser-Unterstützung: SharedWorker funktioniert in Desktop-Chrome, Edge, Firefox und Safari 16+. Auf Android fehlte die Unterstützung lange. Chrome für Android hat sie erst mit Version 142 bekommen, Samsung Internet unterstützt SharedWorker nicht. Frag die Unterstützung also immer mit
'SharedWorker' in windowab und nutze bei BedarfBroadcastChannelals Ersatz. - Same-Origin: Die Skript-URL muss denselben Ursprung wie das Dokument haben, sonst wirft der Konstruktor einen
SecurityError. Eine ungültige URL führt zu einemSyntaxError. Private Fenster und unterschiedliche Speicher-Partitionen (z. B. Third-Party-iframes) teilen sich keine Instanz. - Identität: Welche Instanz geteilt wird, hängt von URL und
nameab. Hat eine bestehende Instanz einen anderentypeoder anderecredentials, löst das einen Fehler aus. - Port starten: Setzt du nur
port.onmessage, wird der Port automatisch gestartet. MitaddEventListener('message', …)musst duport.start()selbst aufrufen, sonst kommen keine Nachrichten an. - Verbindungen aufräumen: Es gibt kein zuverlässiges Ereignis, wenn ein Tab geschlossen wird. Getrennte Ports solltest du selbst verwalten, etwa mit einer Abmelde-Nachricht bei
pagehideoder mit Heartbeats. - Fehlersuche: Die Konsole des Workers findest du in Chrome unter
chrome://inspect/#workers, in Firefox unterabout:debugging. - Im Worker gibt es kein DOM. Verfügbar sind unter anderem
fetch,IndexedDBundWebSocket.