Signatur
Beschreibung
Mit postMessage() schickt der Haupt-Thread (oder ein übergeordneter Worker) Daten an einen Worker. Im Worker kommt die Nachricht als message-Ereignis an; die Daten stehen dann unter event.data. Die Kommunikation läuft asynchron: Der Aufruf kehrt sofort zurück, der Worker verarbeitet die Nachricht in seiner eigenen Ereignisschleife.
Die Nachricht wird mit dem Structured-Clone-Algorithmus kopiert. Dadurch lassen sich neben einfachen Werten auch Object, Array, Map, Set, Date, RegExp, Blob, File, ArrayBuffer, typisierte Arrays und zyklische Strukturen übertragen. Funktionen, DOM-Knoten, Symbole und Klasseninstanzen samt Prototyp gehen dabei nicht mit bzw. lösen einen Fehler aus.
Bei großen Binärdaten sollte man übertragbare Objekte (Transferables) wie ArrayBuffer, MessagePort, ImageBitmap oder OffscreenCanvas im zweiten Argument angeben. Sie werden dann nicht kopiert, sondern ihr Besitz geht auf den Worker über. Das ist nahezu kostenlos, das Original ist danach im Sender aber unbrauchbar (detached).
Typische Einsatzfälle: rechenintensive Aufgaben (Bildbearbeitung, Parsing, Kryptografie, Kompression) aus dem Haupt-Thread auslagern, damit die Oberfläche flüssig bleibt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $message Pflicht | any | Die zu sendenden Daten. Jeder Wert, den der Structured-Clone-Algorithmus kopieren kann. Im Worker erreichbar über event.data. |
|
| $transfer | Array<Transferable> | [] | Liste übertragbarer Objekte (z. B. ArrayBuffer, MessagePort, ImageBitmap, OffscreenCanvas), deren Besitz an den Worker übergeht, statt sie zu kopieren. |
| $options | { transfer?: Array<Transferable> } | {} | Alternative Form: Objekt mit der Eigenschaft transfer, gleichbedeutend mit dem Array-Argument. |
Beispiele
Einfache Nachricht senden und Antwort empfangen
// main.js
const worker = new Worker('worker.js');
worker.addEventListener('message', (event) => {
console.log('Ergebnis vom Worker:', event.data);
});
worker.postMessage({ type: 'sum', values: [1, 2, 3, 4] });
// worker.js
self.addEventListener('message', (event) => {
const { type, values } = event.data;
if (type === 'sum') {
const total = values.reduce((a, b) => a + b, 0);
self.postMessage(total);
}
});
ArrayBuffer ohne Kopie übertragen (Transfer)
const worker = new Worker('worker.js');
const buffer = new ArrayBuffer(8 * 1024 * 1024); // 8 MB
// Besitz wird übertragen statt kopiert
worker.postMessage({ buffer }, [buffer]);
// Alternativ: worker.postMessage({ buffer }, { transfer: [buffer] });
console.log(buffer.byteLength); // Buffer ist im Haupt-Thread jetzt detached
Promise-basierte Anfrage/Antwort mit ID
const worker = new Worker('worker.js');
const pending = new Map();
let nextId = 0;
worker.onmessage = ({ data }) => {
const { id, result, error } = data;
const entry = pending.get(id);
if (!entry) return;
pending.delete(id);
error ? entry.reject(new Error(error)) : entry.resolve(result);
};
const callWorker = (payload) =>
new Promise((resolve, reject) => {
const id = nextId++;
pending.set(id, { resolve, reject });
worker.postMessage({ id, payload });
});
// worker.js:
// self.onmessage = ({ data }) =>
// self.postMessage({ id: data.id, result: data.payload.toUpperCase() });
const result = await callWorker('hallo worker');
console.log(result);
Fehler bei nicht klonbaren Daten abfangen
const worker = new Worker('worker.js');
try {
worker.postMessage({ callback: () => 42 });
} catch (err) {
console.error(err.name); // Funktionen sind nicht klonbar
}
// Wichtig · Fallstricke
- DataCloneError: Funktionen, DOM-Knoten,
Error-Unterklassen mit eigenen Eigenschaften und Ähnliches lassen sich nicht klonen.postMessage()wirft dann synchron eineDOMExceptionmit dem NamenDataCloneError. - Prototypen gehen verloren: Klasseninstanzen kommen als einfache Objekte an; Methoden und Getter fehlen dann. Gegebenenfalls im Worker neu instanziieren.
- Transfer macht das Original unbrauchbar: Nach dem Transfer hat ein
ArrayBufferim Sender diebyteLength0. Wird dasselbe Objekt zweimal in der Transfer-Liste angegeben oder ist es schon detached, gibt es einenDataCloneError. - Performance: Große Objekte zu klonen kostet Zeit auf beiden Seiten. Für Binärdaten Transferables nutzen, für gemeinsam genutzten Speicher
SharedArrayBuffer(erfordert Cross-Origin-Isolation per COOP/COEP-Header). - Kein targetOrigin: Anders als
window.postMessage()gibt es hier keinen Ursprungs-Parameter, weil ein Worker immer demselben Ursprung angehört. Trotzdem sollte der Worker eingehende Daten prüfen, bevor er sie weiterverarbeitet. - Reihenfolge: Nachrichten kommen in der Sendereihenfolge an. Sie werden auch dann gepuffert, wenn das Worker-Skript noch lädt.
- Nach
worker.terminate()werden Nachrichten stillschweigend verworfen, einen Fehler gibt es nicht. - Kompatibilität: In allen modernen Browsern und in Deno verfügbar. Die Variante mit
options-Objekt gibt es erst in neueren Versionen (Chrome 77+, Firefox 103+, Safari 15+). In Node.js heißt das Pendantworker_threads, dort mitworker.postMessage().