DEV Community

loading...
Cover image for Communicating between browser tabs

Communicating between browser tabs

Baedyl
・2 min read

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 ?

Discussion (12)

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 Author

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 Author

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
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
ben profile image
Ben Halpern

Interesting!

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
Luong Van Nghia

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

Collapse
baedyl profile image
Baedyl Author

Definetly! Thanks for your feedback!