The first is probably the worst solution - you need to open a window from your current window and then you can communicate only as long as you keep the windows open. If you reload the page in any of the windows, you most likely lost the communication.

Second approach, using postMessage, probably enables cross-origin communication, but suffers the same problem as the first approach. You need to maintain a window object.

Third way, using cookies, store some data in the browser, which can effectively look like sending a message to all windows on the same domain, but the problem is that you can never know if all tabs read the "message" already or not before cleaning up. You have to implement some sort of timeout to read the cookie periodically. Furthermore you are limited by maximum cookie length, which is 4KB.

Fourth solution, using localStorage, seemed to overcome the limitations of cookies, and it can be even listen-to using events. How to use it is described in the accepted answer.

Edit 2018: the accepted answer still works, but there is a newer solution for modern browsers, to use BroadcastChannel. See the other answer for a simple example describing how to easily transmit message between tabs by using BroadcastChannel.

I created a library over localStorage and sessionStorage to manage client-side data storage. You can do stuff like storageManager.savePermanentData('data', 'key'); or storageManager.saveSyncedSessionData('data', 'key'); based on how you want your data behave. It really simplifies the process. Full article here: ebenmonney.com/blog/…
– adentumDec 14 '16 at 11:28

I've created library sysend.js few years ago, in latest version it use BroadcastChannel. You can test the library by opening this page twice jcubic.pl/sysend.php, it also work with different origin if you provide iframe proxy.
– jcubicOct 21 '18 at 13:16

Do i consider sub domain as a same origin? I mean, I do have below three domain, do they communicate through broadcastchannel api? alpha.firstdomain.com, beta.firstdomain.com, gama.firstdomain.com
– Tejas PatelApr 15 '19 at 8:24

10 Answers
10

Edit 2018: You may better use BroadcastChannel for this purpose, see other answers below. Yet if you still prefer to use localstorage for communication between tabs, do it this way:

In order to get notified when a tab sends a message to other tabs, you simply need to bind on 'storage' event. In all tabs, do this:

$(window).on('storage', message_receive);

The function message_receive will be called every time you set any value of localStorage in any other tab. The event listener contains also the data newly set to localStorage, so you don't even need to parse localStorage object itself. This is very handy because you can reset the value just right after it was set, to effectively clean up any traces. Here are functions for messaging:

// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
localStorage.setItem('message',JSON.stringify(message));
localStorage.removeItem('message');
}
// receive message
//
function message_receive(ev)
{
if (ev.originalEvent.key!='message') return; // ignore other keys
var message=JSON.parse(ev.originalEvent.newValue);
if (!message) return; // ignore empty msg or msg reset
// here you act on messages.
// you can send objects like { 'command': 'doit', 'data': 'abcd' }
if (message.command == 'doit') alert(message.data);
// etc.
}

So now once your tabs bind on the onstorage event, and you have these two functions implemented, you can simply broadcast a message to other tabs calling, for example:

message_broadcast({'command':'reset'})

Remember that sending the exact same message twice will be propagated only once, so if you need to repeat messages, add some unique identifier to them, like

Also remember that the current tab which broadcasts the message doesn't actually receive it, only other tabs or windows on the same domain.

You may ask what happens if the user loads a different webpage or closes his tab just after the setItem() call before the removeItem(). Well, from my own testing the browser puts unloading on hold until the entire function message_broadcast() is finished. I tested to put inthere some very long for() cycle and it still waited for the cycle to finish before closing. If the user kills the tab just inbetween, then the browser won't have enough time to save the message to disk, thus this approach seems to me like safe way how to send messages without any traces. Comments welcome.

can you ignore the remove event before invoking JSON.parse()?
– dandavisJan 30 '15 at 7:33

1

keep in mind the event data limit, including pre-existing localStorage data. it might be better/safer to use the storage events just for messaging instead of shipping. like when you get a postcard telling you to pickup a package at the post office... also, localstorage goes to the hard drive, so it might leave inadvertent caches and affect logs, which is another reason to consider a different transport mechanism for the actual data.
– dandavisJan 30 '15 at 7:37

Web storage can be viewed simplistically as an improvement on cookies, providing much greater storage capacity. If you look at the Mozilla source code we can see that 5120KB (5MB which equals 2.5 Million chars on Chrome) is the default storage size for an entire domain. This gives you considerably more space to work with than a typical 4KB cookie.

The data is not sent back to the server for every HTTP request (HTML, images, JavaScript, CSS, etc) - reducing the amount of traffic between client and server.

The data stored in localStorage persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.

Cons:

It works on same-origin policy. So, data stored will only be able available on the same origin.

Changes are only available per window (or tab in browsers like Chrome and Firefox). Changes made are saved and available for the current page, as well as future visits to the site on the same window. Once the window is closed, the storage is deleted

Cons:

The data is available only inside the window/tab in which it was set.

The data is not persistent i.e. it will be lost once the window/tab is closed.

Like localStorage, tt works on same-origin policy. So, data stored will only be able available on the same origin.

As a data point, the WebKit implementation (used by Safari and Chrome) doesn't currently enforce any limits (other than those imposed by running out of memory).

Cons:

Need to open a window from the current window and then can communicate only as long as you keep the windows open.

Security concerns - Sending strings via postMessage is that you will pick up other postMessage events published by other JavaScript plugins, so be sure to implement a targetOrigin and a sanity check for the data being passed on to the messages listener.

Using postMessage to communicate between multiple tabs and at the same time using sessionStorage in all the newly opened tabs/windows to persist data being passed. Data will be persisted as long as the tabs/windows remain opened. So, even if the opener tab/window gets closed, the opened tabs/windows will have the entire data even after getting refreshed.

I have written a JavaScript library for this, named AcrossTabs which uses postMessage API to communicate between cross-origin tabs/windows and sessionStorage to persist the opened tabs/windows identity as long as they live.

Another method that people should consider using is Shared Workers. I know it's a cutting edge concept, but you can create a relay on a Shared Worker that is MUCH faster than localstorage, and doesn't require a relationship between the parent/child window, as long as you're on the same origin.

New version also support Cross-Domain communication, if you include special proxy.html file on target domain and call proxy function from source domain:

sysend.proxy('https://target.com');

(proxy.html it's very simple html file, that only have one script tag with the library).

If you want two way communication you need to do the same on target.com domain.

NOTE: If you will implement same functionality using localStorage, there is issue in IE. Storage event is sent to the same window, which triggered the event and for other browsers it's only invoked for other tabs/windows.

Just wanted to give you some kudo's for this. Nice sweet little addition that is simple and allows me communicate between my tabs to keep the logout warning software from kicking people off. Nice job. I highly recommend this if you want a simple to use messaging solution.
– BrownPonyJul 3 '19 at 19:30

I created a module that works equal to the official Broadcastchannel but has fallbacks based on localstorage, indexeddb and unix-sockets. This makes sure it always works even with Webworkers or NodeJS. See pubkey:BroadcastChannel