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')
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)
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
}
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()
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)
Interesting. In the past I used
localStorage
with thestorage
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!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.
I actually tried using local storage for this matter and could not achieve the same result. Just do it!
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 ?
Starting at Chrome 54 and Firefox 38, the complete list can be found here: developer.mozilla.org/en-US/docs/W...
You mean here: developer.mozilla.org/en-US/docs/W... ... good to know, very useful!
Interesting!
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.
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.
This looks great but for now localstorage will have to suffice even though its harder.. at least it is supported by all browsers.
I think "communicating" between tabs is cooler than "share data" man.
Thanks for your share !
Definetly! Thanks for your feedback!
Good to know this API.