DEV Community

Cover image for Communicating between browser tabs
Baedyl
Baedyl

Posted on

Communicating between browser tabs

I recently came across the issue of sharing some data between different tabs of the same web application. Using OAuth to retrieve an external provider's API key, saving it and finally displaying it on our platform. The first solution implied reloading the entire page. But the user experience was heavily compromised. In a SPA point of vue, imagine being in /process/emailing/... and redirected to /process 😕

While looking for a more suitable solution, I came across the Broadcast Channel API.

It allows communication between different documents (in different windows, tabs, frames or iframes) of the same origin. Messages are broadcasted via a message event fired at all BroadcastChannel objects listening to the channel.

Let's start by creating a broadcast channel:

const channel = new BroadcastChannel('oauth')
Enter fullscreen mode Exit fullscreen mode

Here we specified the name oauth that will later be used in other parts of our app to listen on any message sent through this channel.

channel.postMessage(data)
Enter fullscreen mode Exit fullscreen mode

Here we send a message and, we can pass any object we like. In our case, we just needed an indication to know a certain task was done so the content did not really matter, feel free to pass useful data according to your need.

The data sent can be any of those supported values:

  • All primitive types, excluding symbols
  • Arrays
  • Object literals
  • String, Date, RegExp objects
  • Blob, File, FileList objects
  • ArrayBuffer, ArrayBufferView objects
  • FormData objects
  • ImageData objects
  • Map and Set objects

Now we need to listen to the same channel in other parts of our app. To do so, we create a channel with the same name and use the onmessage event handler

const channel = new BroadcastChannel('oauth')
channel.onmessage = (e) => {
  // Business logic here
  // data sent through the channel is available at e.data
}
Enter fullscreen mode Exit fullscreen mode

And that's it! We successfully sent data from a different window, tab or frame to another 😀.

Finally, to make a channel stop receiving messages you can close it using:

channel.close()
Enter fullscreen mode Exit fullscreen mode

You can achieve the same result using the SharedWorker API or even Local Storage but, personally I found this method the most intuitive. Do you know any other alternative ?

Top comments (13)

Collapse
 
alvaromontoro profile image
Alvaro Montoro

Interesting. In the past I used localStorage with the storage event. But this seems to work in a different way, I need to look into this because it looks simpler and more complete. Thanks for sharing!

Collapse
 
link2twenty profile image
Andrew Bone

Main problem is it's not really fully supported yet. If we ignore IE (and we should) safari still doesn't have support, which means iOS doesn't either.

If you want to track it here's the issue on webkit.

Collapse
 
baedyl profile image
Baedyl

I actually tried using local storage for this matter and could not achieve the same result. Just do it!

Collapse
 
leob profile image
leob

That's incredibly interesting, hadn't heard about it, there are so many new and useful APIs in the evolving browser standards, it's hard to keep track of them ... which browsers (versions) support this new API ?

Collapse
 
baedyl profile image
Baedyl

Starting at Chrome 54 and Firefox 38, the complete list can be found here: developer.mozilla.org/en-US/docs/W...

Collapse
 
leob profile image
leob

You mean here: developer.mozilla.org/en-US/docs/W... ... good to know, very useful!

Collapse
 
ben profile image
Ben Halpern

Interesting!

Collapse
 
thormeier profile image
Pascal Thormeier

TIL, that will come in handy, thank you! Browser support seems to be good, although no Safari (neither desktop nor iOS) supports it, but there seems to be a polyfill.

Collapse
 
patzistar profile image
Patrick Schadler

Didn't knew that this is possible, thanks! Would probably went the localStorage route or even websockets and a backend logic, which handles all the logic and sends updates to all listener.

Collapse
 
jsnanigans profile image
Brendan Mullins

This looks great but for now localstorage will have to suffice even though its harder.. at least it is supported by all browsers.

Collapse
 
egotr profile image
nghialv

I think "communicating" between tabs is cooler than "share data" man.
Thanks for your share !

Collapse
 
baedyl profile image
Baedyl

Definetly! Thanks for your feedback!

Collapse
 
mrdulin profile image
official_dulin

Good to know this API.