What does postMessage() do between threads?
What postMessage() does
postMessage()is a method that lets you send a message from one context to another (for example, from the main thread to a Web Worker or vice versa).
It does not perform direct memory access, but passes a copy of the data, asynchronously, through the message passing mechanism.
What this looks like with a Web Worker
Example
// main.js
const worker = new Worker('worker.js');
// Send a message to the worker
worker.postMessage({ task: 'sum', a: 5, b: 7 });
// Get the response
worker.onmessage = (event) => {
console.log('Response from the worker:', event.data);
};// worker.js
onmessage = (event) => {
const { task, a, b } = event.data;
if (task === 'sum') {
postMessage(a + b); // send the result back
}
};What happens:
- The main thread calls
worker.postMessage(...); - The message is serialized and placed into the worker's message queue;
- The
onmessageevent fires in the worker; - The worker processes it and replies via
postMessage(); - The main thread catches that event via
onmessage.
All of this happens asynchronously; JavaScript does not wait for the worker to respond.
What exactly gets passed
You can pass:
- Primitives (
string,number,boolean,null,undefined); - Objects (JSON-compatible);
ArrayBuffer,Blob,File,ImageBitmap;- Transferable objects - passed without copying.
What Transferable Objects are
Normally data is copied when passed between threads (via structured clone). But for large binary data this is expensive.
Transferable objects (for example,
ArrayBuffer) can be "passed by reference"
- without copying, just by transferring ownership.
Example:
const buffer = new ArrayBuffer(1024);
worker.postMessage(buffer, [buffer]); // pass it as transferableAfter transfer, buffer becomes invalid in the main thread (because "ownership" has moved to the worker).
This is 10-100 times faster when transferring large data.
What postMessage() returns
Nothing.
It simply queues a message on the other side.
The receiver catches it through the message event:
worker.onmessage = (event) => {
console.log(event.data);
};Communication in both directions
| From | Method | Listener |
|---|---|---|
| Main thread -> worker | worker.postMessage() | onmessage in the worker |
| Worker -> main thread | postMessage() | worker.onmessage |
An "echo" example (echo worker)
// worker.js
onmessage = (event) => {
postMessage(`Echo: ${event.data}`);
};// main.js
worker.postMessage('Hello!');
worker.onmessage = (e) => console.log(e.data);
// -> "Echo: Hello!"postMessage() is not only for Web Workers
This method is universal; it works across different browser contexts:
| Where it is used | Example |
|---|---|
| window -> iframe | iframe.contentWindow.postMessage(data, origin) |
| iframe -> parent | window.parent.postMessage(data, origin) |
| between tabs | otherWindow.postMessage(data, origin) |
| Service Worker <-> Main | navigator.serviceWorker.controller.postMessage(data) |
| Web Worker <-> Main | worker.postMessage(data) |
Example: window.postMessage() between pages
// Page A
const popup = window.open('https://example.com/popup.html');
popup.postMessage('Hi, page B!', 'https://example.com');
// Page B
window.addEventListener('message', (event) => {
if (event.origin === 'https://example.com') {
console.log('Message received:', event.data);
}
});Very useful for safe communication between different domains (CORS-safe).
How it works under the hood
- When
postMessage()is called, the data is serialized using the Structured Clone Algorithm; - A copy of the data is placed into the receiver's queue;
- When the thread frees up, the browser calls the
onmessage(event)handler; - The data is available in
event.data.
What is inside event
onmessage = (event) => {
console.log(event.data); // the data itself
console.log(event.origin); // the source (for windows/iframes)
console.log(event.ports); // MessagePort, if any
console.log(event.source); // who sent the message
};A simple analogy
Think of postMessage() as a postal service between offices.
Each office (a JS thread) works in isolation.
When one wants to pass data to another,
it drops a letter (a message) into a mailbox (postMessage).
The other office picks up the letter when it has time (onmessage).
Summary
| What it does | Explanation |
|---|---|
postMessage() | Sends a message between threads / contexts |
| Works asynchronously | Does not block the code |
| Passes data by copy | Through structured clone |
| Optimization | Transferable objects - without copying |
| Two-way communication | Both threads can send and receive |
| Used where | Web Workers, iframes, windows, Service Workers |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.