Signatur
Beschreibung
postMessage() wird innerhalb eines Dedicated Workers aufgerufen, meist einfach als globales postMessage(...) oder self.postMessage(...). Die Nachricht landet beim zugehörigen Worker-Objekt im erzeugenden Thread. Dort löst sie ein message-Event aus, dessen Eigenschaft event.data die Daten enthält.
Die Daten werden mit dem Structured-Clone-Algorithmus kopiert. Erlaubt sind damit Objekte, Arrays, Map, Set, Date, RegExp, Blob, ArrayBuffer, typisierte Arrays und vieles mehr. Funktionen, DOM-Knoten und Klasseninstanzen samt Prototyp lassen sich nicht übertragen. Der Empfänger bekommt immer eine unabhängige Kopie, nie eine gemeinsame Referenz.
Bei großen Binärdaten kopiert man besser nicht, sondern gibt übertragbare Objekte (ArrayBuffer, MessagePort, ImageBitmap, OffscreenCanvas, ReadableStream …) über die Transfer-Liste weiter. Dann wechselt der Besitz ohne Kopie. Im Worker ist das Objekt danach unbrauchbar, ein ArrayBuffer hat dann zum Beispiel byteLength === 0.
Typische Einsatzfälle: Ergebnisse rechenintensiver Arbeiten zurückmelden (Parsing, Bildverarbeitung, Kryptografie), Fortschritt melden und Fehler oder Status an die Oberfläche weitergeben, ohne den Hauptthread zu blockieren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $message Pflicht | any | Die zu sendenden Daten. Jeder per Structured Clone kopierbare Wert, z. B. string, number, Objekt, Array, ArrayBuffer oder Blob. Kommt beim Empfänger als event.data an. |
|
| $transfer | Transferable[] | [] | Optionales Array übertragbarer Objekte, deren Besitz an den Empfänger übergeht, statt dass sie kopiert werden. Sie müssen auch in message vorkommen, sonst erhält der Empfänger keinen Zugriff darauf. |
| $options | { transfer?: Transferable[] } | {} | Alternative Form zum Array: ein Objekt mit der Eigenschaft transfer, z. B. postMessage(data, { transfer: [buf] }). |
Beispiele
Einfaches Ergebnis an den Hauptthread melden
// worker.js
self.addEventListener('message', (event) => {
const { numbers } = event.data;
const sum = numbers.reduce((a, b) => a + b, 0);
// Ergebnis zurück an den Hauptthread
postMessage({ type: 'result', sum });
});
// main.js
const worker = new Worker('worker.js');
worker.addEventListener('message', (event) => {
console.log('Summe:', event.data.sum);
});
worker.postMessage({ numbers: [1, 2, 3, 4, 5] });
Fortschritt während einer langen Berechnung melden
// worker.js
self.onmessage = ({ data: { limit } }) => {
const primes = [];
for (let n = 2; n <= limit; n++) {
let isPrime = true;
for (let d = 2; d * d <= n; d++) {
if (n % d === 0) { isPrime = false; break; }
}
if (isPrime) primes.push(n);
if (n % 25000 === 0) {
postMessage({ type: 'progress', percent: Math.round((n / limit) * 100) });
}
}
postMessage({ type: 'done', count: primes.length });
};
// main.js
const worker = new Worker('worker.js');
worker.onmessage = ({ data }) => {
if (data.type === 'progress') console.log(`${data.percent} %`);
if (data.type === 'done') console.log(`Primzahlen gefunden: ${data.count}`);
};
worker.postMessage({ limit: 100000 });
ArrayBuffer ohne Kopie übertragen (Transferable)
// worker.js
self.onmessage = () => {
const buffer = new ArrayBuffer(16 * 1024 * 1024); // 16 MB
new Uint8Array(buffer).fill(42);
// Besitz übergeben statt kopieren
postMessage({ buffer }, { transfer: [buffer] });
// Alternativ: postMessage({ buffer }, [buffer]);
console.log('Im Worker danach:', buffer.byteLength);
};
// main.js
const worker = new Worker('worker.js');
worker.onmessage = ({ data }) => {
const view = new Uint8Array(data.buffer);
console.log('Empfangen:', view.byteLength, 'Bytes, erstes Byte =', view[0]);
};
worker.postMessage('start');
Fehler strukturiert zurückmelden
// worker.js
self.onmessage = ({ data }) => {
try {
const parsed = JSON.parse(data);
postMessage({ ok: true, parsed });
} catch (err) {
// Error-Objekte sind klonbar, eigene Eigenschaften aber nicht garantiert
postMessage({ ok: false, message: err.message });
}
};
// main.js
const worker = new Worker('worker.js');
worker.onmessage = ({ data }) => {
console.log(data.ok ? data.parsed : `Fehler: ${data.message}`);
};
worker.postMessage('{ kaputt');
// Wichtig · Fallstricke
- DataCloneError: Nicht klonbare Werte wie Funktionen, DOM-Knoten, Symbole oder Objekte mit Funktionen als Eigenschaften lösen synchron eine
DOMExceptionvom TypDataCloneErroraus. Klasseninstanzen kommen als einfache Objekte ohne Prototyp und Methoden an. - Kein
targetOrigin: Anders alswindow.postMessage()gibt es hier keinen Ursprungsparameter, denn der Empfänger ist immer eindeutig der erzeugende Thread. - Transfer-Fallen: Nach dem Übertragen ist das Objekt im Worker abgekoppelt (detached). Wer es weiter benutzt, bekommt leere Puffer oder einen
TypeError. Steht dasselbe Objekt doppelt in der Transfer-Liste oder ist es schon abgekoppelt, wird einDataCloneErrorausgelöst. - Leistung: Das Klonen großer Objektbäume kostet auf beiden Seiten spürbar Zeit. Für Binärdaten deshalb Transferables oder
SharedArrayBufferverwenden. Letzterer setzt Cross-Origin-Isolation (COOP/COEP-Header) voraus. - Sicherheit: Empfangene Daten im Hauptthread nicht ungeprüft in
innerHTMLeinfügen, vor allem wenn der Worker Fremddaten verarbeitet. Sonst droht XSS. - Kompatibilität: In allen modernen Browsern verfügbar. Die Form mit Options-Objekt (
{ transfer }) fehlt in sehr alten Browsern, dort das Array verwenden. Bei Shared Workers gibt es diese Methode nicht, dort läuft die Kommunikation überMessagePort.postMessage().