Broadcast Channel API
Communicate in real time between multiple browser tabs, windows, or workers from the same origin using the BroadcastChannel API.
Overview
Key Points
- •`new BroadcastChannel("name")` joins a named channel all same-origin contexts on the same channel receive messages
- •`channel.postMessage(data)` sends to ALL other listeners on the channel (sender does NOT receive its own message)
- •`channel.onmessage = handler` or `channel.addEventListener("message", handler)` to receive
- •Messages are structured-cloned can send objects, arrays, typed arrays, not functions
- •Sender does NOT receive its own broadcast
- •Works between: tabs, iframes (same origin), service workers, shared workers, dedicated workers
- •`channel.close()` frees resources and removes from the channel important in SPAs to prevent leaks
Examples
Cross-tab authentication synchronization
<!-- In every tab/page of your app -->
<script>
const authChannel = new BroadcastChannel('auth');
// Broadcast logout to all tabs
function logout() {
clearLocalStorage();
authChannel.postMessage({ type: 'LOGOUT' });
window.location.href = '/login';
}
// Receive logout from another tab
authChannel.onmessage = (event) => {
if (event.data.type === 'LOGOUT') {
clearLocalStorage();
window.location.href = '/login';
}
if (event.data.type === 'LOGIN') {
// Another tab logged in refresh the page to pick up the session
window.location.reload();
}
};
// Broadcast login event
function onLoginSuccess(user) {
authChannel.postMessage({ type: 'LOGIN', user });
}
// Clean up when the tab closes
window.addEventListener('beforeunload', () => authChannel.close());
</script>A single logout in any tab propagates to all open tabs essential for security-sensitive apps.
Service worker notifying all tabs of a cache update
// In sw.js
const updateChannel = new BroadcastChannel('sw-updates');
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v2').then(cache =>
cache.addAll(['/app.js', '/styles.css', '/'])
).then(() => {
// Notify all tabs that new content is available
updateChannel.postMessage({
type: 'UPDATE_AVAILABLE',
version: 'v2'
});
})
);
});
// In the page
const swChannel = new BroadcastChannel('sw-updates');
swChannel.onmessage = (event) => {
if (event.data.type === 'UPDATE_AVAILABLE') {
// Show banner: "New version available click to refresh"
document.getElementById('update-banner').style.display = 'block';
}
};The service worker broadcasts to tabs a clean decoupled alternative to service worker postMessage.
Shared counter across multiple tabs
<div>
Counter: <span id="count">0</span>
<button id="inc">Increment</button>
</div>
<script>
const channel = new BroadcastChannel('counter');
let count = parseInt(localStorage.getItem('counter') || '0');
document.getElementById('count').textContent = count;
document.getElementById('inc').addEventListener('click', () => {
count++;
localStorage.setItem('counter', count);
document.getElementById('count').textContent = count;
// Broadcast new value to all other tabs
channel.postMessage({ type: 'COUNT_UPDATE', value: count });
});
// Receive update from another tab
channel.onmessage = (event) => {
if (event.data.type === 'COUNT_UPDATE') {
count = event.data.value;
document.getElementById('count').textContent = count;
}
};
</script>Combine BroadcastChannel with localStorage for both persistence and real-time cross-tab sync.
Common Mistakes
- Forgetting that the sender does NOT receive its own broadcast update your own UI state separately, then broadcast to others
- Not calling `channel.close()` when a component unmounts in a SPA listeners accumulate and cause memory leaks
- Using BroadcastChannel for large data messages are structured-cloned (copied), not shared; for large shared data, use SharedArrayBuffer
Note
For debugging, open the same page in two browser tabs. Changes in tab 1 should immediately appear in tab 2. Chrome DevTools > Application > Background Services > BroadcastChannel shows all messages in real-time.
Exercises
Write HTML to solve each exercise. Use Preview to see it render in a live iframe, then mark as done.
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4