Storage Cross-Tab Communication
Communicate between browser tabs using storage
AdvancedTopic: LocalStorage/SessionStorage
JavaScript Storage Cross-Tab Communication Program
This program helps you to learn the fundamental structure and syntax of JavaScript programming.
// Method 1: Basic cross-tab messaging
class CrossTabMessenger {
constructor(channel) {
this.channel = channel;
this.listeners = [];
this.setupListener();
}
setupListener() {
window.addEventListener('storage', (e) => {
if (e.key === this.channel && e.newValue) {
const message = JSON.parse(e.newValue);
this.listeners.forEach(listener => listener(message));
}
});
}
send(message) {
localStorage.setItem(this.channel, JSON.stringify({
...message,
timestamp: Date.now(),
tabId: this.getTabId()
}));
// Clear immediately to allow same message again
setTimeout(() => localStorage.removeItem(this.channel), 100);
}
onMessage(callback) {
this.listeners.push(callback);
}
getTabId() {
let tabId = sessionStorage.getItem('tabId');
if (!tabId) {
tabId = 'tab_' + Date.now() + '_' + Math.random();
sessionStorage.setItem('tabId', tabId);
}
return tabId;
}
}
const messenger = new CrossTabMessenger('app-messages');
messenger.onMessage((message) => {
console.log('Message received:', message);
});
messenger.send({ type: 'user-updated', data: { name: 'John' } });
// Method 2: Broadcast channel API (modern)
if ('BroadcastChannel' in window) {
const channel = new BroadcastChannel('app-channel');
channel.postMessage({ type: 'notification', message: 'Hello from tab 1' });
channel.onmessage = function(e) {
console.log('Broadcast received:', e.data);
};
}
// Method 3: Shared state manager
class SharedState {
constructor(key) {
this.key = key;
this.state = this.loadState();
this.listeners = [];
this.setupListener();
}
loadState() {
const stored = localStorage.getItem(this.key);
return stored ? JSON.parse(stored) : {};
}
setupListener() {
window.addEventListener('storage', (e) => {
if (e.key === this.key) {
this.state = JSON.parse(e.newValue);
this.notifyListeners();
}
});
}
setState(updates) {
this.state = { ...this.state, ...updates };
localStorage.setItem(this.key, JSON.stringify(this.state));
this.notifyListeners();
}
getState() {
return this.state;
}
subscribe(callback) {
this.listeners.push(callback);
}
notifyListeners() {
this.listeners.forEach(listener => listener(this.state));
}
}
const sharedState = new SharedState('app-state');
sharedState.subscribe((state) => {
console.log('State updated:', state);
});
sharedState.setState({ user: 'John', theme: 'dark' });
// Method 4: Leader election
class TabLeader {
constructor() {
this.leaderKey = 'tab-leader';
this.heartbeatInterval = null;
this.checkLeader();
}
checkLeader() {
const leader = localStorage.getItem(this.leaderKey);
const now = Date.now();
if (!leader) {
this.becomeLeader();
} else {
const [leaderTabId, timestamp] = leader.split(':');
const age = now - parseInt(timestamp);
// If leader is inactive for 5 seconds, take over
if (age > 5000) {
this.becomeLeader();
}
}
// Check every second
setTimeout(() => this.checkLeader(), 1000);
}
becomeLeader() {
const tabId = this.getTabId();
localStorage.setItem(this.leaderKey, tabId + ':' + Date.now());
this.startHeartbeat();
console.log('Became leader');
}
startHeartbeat() {
this.heartbeatInterval = setInterval(() => {
const tabId = this.getTabId();
localStorage.setItem(this.leaderKey, tabId + ':' + Date.now());
}, 2000);
}
isLeader() {
const leader = localStorage.getItem(this.leaderKey);
if (!leader) return false;
const [leaderTabId] = leader.split(':');
return leaderTabId === this.getTabId();
}
getTabId() {
let tabId = sessionStorage.getItem('tabId');
if (!tabId) {
tabId = 'tab_' + Date.now();
sessionStorage.setItem('tabId', tabId);
}
return tabId;
}
}
const tabLeader = new TabLeader();Output
Message received: { type: 'user-updated', data: { name: 'John' }, timestamp: 1234567890, tabId: 'tab_1234567890' }
Broadcast received: { type: 'notification', message: 'Hello from tab 1' }
State updated: { user: 'John', theme: 'dark' }
Became leaderUnderstanding Storage Cross-Tab Communication
Cross-tab communication syncs data.
Methods
•Storage events: Cross-tab
•BroadcastChannel: Modern API
•Shared state: Common pattern
•Leader election: Coordination
Storage Events
•Fires in other tabs
•Not in same tab
•Use for messaging
BroadcastChannel
•Modern API
•Better performance
•Easier to use
•Browser support varies
Use Cases
•Sync user state
•Notifications
•Real-time updates
•Coordination
Best Practices
•Use BroadcastChannel if available
•Fallback to storage events
•Handle errors
•Clean up listeners
Let us now understand every line and the components of the above program.
Note: To write and run JavaScript programs, you need to set up the local environment on your computer. Refer to the complete article Setting up JavaScript Development Environment. If you do not want to set up the local environment on your computer, you can also use online IDE to write and run your JavaScript programs.