Limitations of postMessage
Back in 2012, yes, 2012! That was over a decade ago—I wrote an article about cross-page communication using postMessage.
Fast forward to today, we now have the Broadcast Channel API, another tool for enabling communication between pages.
The major difference between the two lies in their communication models. The Broadcast Channel API adopts a broadcast model instead of the point-to-point model used by postMessage.
Broadcast communication means that any page under the same domain can listen for messages. If Page A sends a message, all other pages on the same domain can receive it simultaneously. This makes the Broadcast Channel API particularly useful for scenarios where real-time data synchronization is required.
Here is Comparison between postMessage and Broadcast Channel API:
Using the Broadcast Channel API is Quite Simple
At first glance, the Broadcast Channel API might look complicated, but using it is surprisingly straightforward. Honestly, the hardest part might just be spelling the API’s name correctly!
Here’s the basic idea: every page that needs to communicate creates a new instance of the same broadcast channel, like this:
const bc = new BroadcastChannel('melin');
And then, other pages can receive this message:
bc.postMessage('hello world');
And then, other pages can receive the message like this:
const bc = new BroadcastChannel('melin');
bc.onmessage = function (event) {
console.log(event.data);
};
And that’s it.
When to use Broadcast Channel API
-
Synchronizing State Across Multiple Tabs or Windows
When a user opens multiple tabs or windows of the same application, you may want to keep the state consistent across all of them. For example:
- User authentication status: If a user logs in or out in one tab, you can broadcast the change to all open tabs to ensure they all reflect the current authentication status.
- Theme preference: If a user changes the theme (dark/light mode) in one tab, you can broadcast the change so all tabs update their appearance.
-
Real-Time Notifications Across Tabs
If your application requires real-time notifications, such as a chat app or a live dashboard:
- Chat updates: New messages received in one tab can be broadcast to other tabs, ensuring that all tabs stay up to date without the need for polling.
- Live updates: In applications like live score tracking or stock market dashboards, real-time updates can be shared across tabs to maintain consistency.
-
Shared Data Across Different Contexts (Tabs, iframes, Workers)
BroadcastChannel allows communication between different contexts within the same origin. This can be used for:
- Shared user settings: Store user preferences (e.g., language, layout, etc.) in one context (such as a main tab) and broadcast the changes to all other contexts.
- Game synchronization: In multiplayer browser games, game states and moves made by players can be broadcast across multiple tabs or iframes, keeping everyone on the same page.
-
Managing Session State or Activity Across Tabs
In cases where users are interacting with the same web application in multiple tabs:
- Preventing duplicate actions: When a user performs an action in one tab (e.g., making a payment), you can broadcast this action to other tabs to prevent the same action from being repeated.
- Shared session management: If the user logs out in one tab, you can broadcast this event to other tabs to automatically log them out as well.
-
Coordinating Tasks in a Worker Pool
For applications that use multiple Web Workers:
- Task distribution: When a task is completed in one worker, the result can be broadcast to other workers to trigger further actions.
- Progress updates: A progress bar or other UI components can be updated in real time as workers complete different steps of a task.
-
Keeping Multiple Iframes Synchronized
In complex web applications that use multiple iframes:
- Cross-iframe communication: Broadcast events between iframes on the same origin, such as when one iframe performs a user action and other iframes need to update accordingly.
- Content syncing: For example, an iframe containing a document editor can broadcast content updates to other iframes that are viewing or editing the same document.
-
Managing Web Application Lifecycle Events
- Tab closure notification: When one tab closes or refreshes, it can notify other tabs to handle session state or to update UI elements (such as a user dashboard).
- Shared event triggers: For instance, a global event such as “maintenance mode” or “version update” can be broadcast to all tabs to trigger UI changes across the application.
-
Handling Background Synchronization Tasks
Applications that need to perform background synchronization across tabs can use BroadcastChannel:
- Syncing data: For applications that keep user data or preferences in sync (such as syncing offline data to the server), BroadcastChannel can notify multiple tabs of successful syncs or sync status changes.
These use cases highlight how BroadcastChannel can be used to create a seamless experience across multiple browser contexts, ensuring that all parts of an application remain in sync.
Compatibility and Other Considerations
The compatibility of the current Broadcast Communication API is quite good. Below is a screenshot from the compatibility data on caniuse.com:
BroadcastChannel can be used not only in the window context but also in Web Workers.
It is not limited to communication between iframes; it also supports communication between different browser tabs. I will not repeat the demonstration here, but it is certainly supported.
Retrieving and Closing the Channel
The channel name can be retrieved using the name attribute, for example:
console.log(bc.name);
To close the channel, you can use the close() method.
bc.close();
Once the channel is closed, attempting to use postMessage() to send data will throw an error. Similarly, using the message event to receive data will fail and trigger the messageerror event.
In the demo above, communication messages are received using the onmessage method. Alternatively, you can bind events using addEventListener, for example:
bc.addEventListener("message", (event) => {
console.log(event.data);
})