Signatur
Beschreibung
Das message-Ereignis tritt auf dem DedicatedWorkerGlobalScope (im Worker erreichbar über self bzw. globalThis) ein, sobald das Elternskript – meist der Hauptthread – mit worker.postMessage(data, transfer) eine Nachricht sendet. Das Ereignisobjekt ist ein MessageEvent. Seine Eigenschaft data enthält eine per Structured Clone kopierte Fassung der gesendeten Daten, ports enthält die mitübertragenen MessagePort-Objekte.
Einen Listener registriert man entweder mit self.addEventListener("message", handler) oder über die Eigenschaft self.onmessage = handler. Mit addEventListener lassen sich mehrere Handler anhängen und über removeEventListener wieder entfernen. onmessage erlaubt dagegen nur genau einen Handler, der bei jeder neuen Zuweisung ersetzt wird.
Typische Einsatzfälle sind rechenintensive Aufgaben wie Bildverarbeitung, Parsing oder Kryptografie, die den Hauptthread nicht blockieren sollen. Der Worker empfängt einen Auftrag, verarbeitet ihn und schickt das Ergebnis mit self.postMessage() zurück. Dieses Ergebnis kommt dann als message-Ereignis auf dem Worker-Objekt im Hauptthread an.
Das Ereignis lässt sich nicht abbrechen und steigt nicht auf (kein Bubbling). Nachrichten, die sich nicht deserialisieren lassen, lösen statt message das Ereignis messageerror aus.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier "message". |
|
| $handler Pflicht | (event: MessageEvent) => void | Callback, der ein MessageEvent erhält. Wichtige Eigenschaften: data (die Nutzdaten), ports (übertragene MessagePorts), origin und lastEventId (bei Dedicated Workers meist leer). |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, signal (AbortSignal zum Entfernen) oder capture. |
Rückgabewert
addEventListener gibt nichts zurück. Der Rückgabewert des Handlers wird ignoriert.Beispiele
Auftrag im Worker empfangen und beantworten (addEventListener)
// worker.js
self.addEventListener("message", (event) => {
const { numbers } = event.data;
const sum = numbers.reduce((a, b) => a + b, 0);
self.postMessage({ sum });
});
// main.js
const worker = new Worker("worker.js");
worker.addEventListener("message", (e) => console.log("Summe:", e.data.sum));
worker.postMessage({ numbers: [1, 2, 3, 4] });
Kurzform mit onmessage und Nachrichtentypen
// worker.js
self.onmessage = ({ data }) => {
switch (data.type) {
case "upper":
self.postMessage(data.text.toUpperCase());
break;
case "stop":
self.close(); // Worker beendet sich selbst
break;
}
};
// main.js
const worker = new Worker("worker.js");
worker.onmessage = (e) => console.log(e.data);
worker.postMessage({ type: "upper", text: "hallo worker" });
worker.postMessage({ type: "stop" });
Listener per removeEventListener und AbortSignal entfernen
// worker.js
const onInit = (event) => {
console.log("Init-Konfiguration:", event.data);
// nur die erste Nachricht als Init behandeln
self.removeEventListener("message", onInit);
};
self.addEventListener("message", onInit);
const controller = new AbortController();
self.addEventListener("message", (e) => {
if (e.data === "ende") controller.abort();
else console.log("Nachricht:", e.data);
}, { signal: controller.signal });
ArrayBuffer ohne Kopie übertragen (Transferable)
// main.js
const worker = new Worker("worker.js");
const buffer = new Uint8Array(1024 * 1024).buffer;
worker.postMessage(buffer, [buffer]);
console.log(buffer.byteLength); // 0 – Besitz übertragen
// worker.js
self.addEventListener("message", (e) => {
console.log("Empfangen:", e.data.byteLength, "Bytes");
});
// Wichtig · Fallstricke
- Structured Clone: Funktionen, DOM-Knoten und Klasseninstanzen (deren Prototyp dabei verloren geht) lassen sich nicht übertragen. Nicht klonbare Werte führen beim Sender zu einer
DataCloneError-Ausnahme. Schlägt die Deserialisierung beim Empfänger fehl, wirdmessageerrorstattmessageausgelöst. - Leistung: Große Datenmengen werden kopiert. Mit Transferables wie
ArrayBuffer,MessagePortoderOffscreenCanvaslässt sich das Kopieren vermeiden. Der Sender verliert dann aber den Zugriff auf das Objekt. - Reihenfolge: Nachrichten, die vor dem Registrieren des Listeners gesendet wurden, werden in eine Warteschlange gestellt und zugestellt, sobald das Worker-Skript geladen ist. Den Listener sollte man trotzdem synchron auf oberster Ebene des Skripts registrieren und nicht erst nach einem
await. - Sicherheit:
event.originist bei Dedicated Workers in der Regel leer. Kommen die Daten ursprünglich aus unsicheren Quellen, müssen sie im Worker trotzdem geprüft werden. - Bei Module Workers (
new Worker(url, { type: \"module\" })) funktioniert das Ereignis identisch. - Kompatibilität: Das Ereignis wird von allen modernen Browsern unterstützt. In Node.js heißt das Gegenstück
parentPort.on(\"message\")ausworker_threads.