Explain Codes LogoExplain Codes Logo

Communication between tabs or windows

javascript
postmessage
broadcastchannel
localstorage
Nikita BarsukovbyNikita Barsukov·Dec 4, 2024
TLDR

For tab communication, it's all about the message and the channel (no, not the TV type). Opt for PostMessage in cross-origin situations:

// Sender tab, a modern-day mailman window.open('http://neighbor.com').postMessage('Hello!', 'http://neighbor.com'); // Receiver tab, picks up the mail window.addEventListener('message', (e) => { if (e.origin === 'http://neighbor.com') console.log(e.data); // Got your mail! });

If you're dealing with same-origin tabs, BroadcastChannel got your back:

// Send a shout-out to the whole neighborhood new BroadcastChannel('chan').postMessage('Party at my place!'); // Neighbor tab, gets the shout-out new BroadcastChannel('chan').onmessage = (e) => console.log(e.data); // Party? Count me in!

When subtlety is your game, localStorage/sessionStorage will serve as your silent messenger across tabs:

// Your personal spy, keeps tabs (pun intended) on storage activities window.addEventListener('storage', (e) => console.log(e.newValue));

To be an expert communicator, use localStorage to set and clear messages. Include unique identifiers for repeated messages, and wait for messageBroadcast() to finish:

function messageBroadcast(channel, message) { localStorage.setItem(channel, JSON.stringify({ id: Date.now(), message })); window.dispatchEvent(new Event('storage')); // Like Rip Van Winkle, waits until after the event } function messageClear(channel) { return new Promise(resolve => { localStorage.removeItem(channel); // Nothing to see here, move along resolve(); // Done and dusted! }); }

In-depth explanation and caveats

Exchange of structured data in BroadcastChannel

When structured data is in play, BroadcastChannel flexes its muscles. Unlike localStorage, it leaves no trace, ensuring your secrets are safe:

let bc = new BroadcastChannel('chan'); let secretMessage = { agentName: 'James', mission: 'Save the world' }; bc.postMessage(secretMessage); // Message delivered, no trace left behind. Totally Bond-style!

localStorage as the town crier

Using the 'storage' event, localStorage takes on the role of a town crier for tabs to receive change notifications. Be careful, Internet Explorer might decide to break up with you over localStorage events in the same window:

window.addEventListener('storage', (e) => { if (e.key === 'chan') { let whisper = JSON.parse(e.newValue); console.log('Hear ye, hear ye: ', whisper); // All hail the town crier! } });

SessionStorage: A trustworthy confidant

When your data is of a sensitive nature, sessionStorage is your go-to. It discreetly holds the data during the page session, only within that tab. Combine with postMessage and you have confidentiality in communication:

// Sender tab, entrusts sessionStorage with data let secretData = { info: 'For Your Eyes Only' }; sessionStorage.setItem('tab_data', JSON.stringify(secretData)); otherWindow.postMessage('Check the safe', 'http://neighbor.com'); // Receiver tab, retrieves the data from the sessionStorage safe window.addEventListener('message', (e) => { if (e.origin === 'http://neighbor.com') { let confidentialData = JSON.parse(sessionStorage.getItem('tab_data')); console.log(confidentialData); // Whoa, juicy secrets! } });

Libraries: Your communication entourage

Sometimes, BroadcastChannel is the attractive but hard to get option due to browser compatibility. Lucky for you, third party libraries like AcrossTabs and sysend.js come in handy. They use postMessage and sessionStorage, and serve you an API with silver platter for communication. Just remember, every target domain needs to be in on the sysend.js party for back-and-forth talks.

Cookies? They crumble sometimes

Cookies might seem sweet, but they come with strings attached. They can't hold too much data or numbers per domain, unlike our trusty ally, localStorage.

Best practices and advice

Polyfills, your guardian angels in disguise

When you're dealing with legends of yore (read: legacy browsers), a polyfill for BroadcastChannel is like having spam protection. Check your browser support and brace for alternatives if you need to.

Friend in need, libraries indeed

Libraries like AcrossTabs or sysend.js offer a hand when you need BroadcastChannel, but compatibility issues stand in the way. They've got your back with zero dependencies, making tab/window communication as smooth as a hot knife through butter.

A stitch in time (and security) saves nine

Security is not an option, it's a necessity. When running postMessage across origins, always validate the origin and sanitize the data. Never underestimate a vill...uh, bad code.