Getting in sync with Broadcast Channel API

Michael P. Dumalag
Red Squirrel
Published in
4 min readJan 31, 2023
Photo by Jonathan Velasquez on Unsplash

In a recent project, securing sensitive personal identifiable information was a top priority. As part of this effort, it was a requirement to ensure that the web application was logged out across all browser tabs and windows whenever a user logged out. As a result, I was in search for a simple method to communicate between tabs and keep them in sync, leading me to explore the Broadcast Channel API.

Image from MDN Web

What is the Broadcast Channel API?

It is a Web API, currently supported by all major browsers, that allows for communication between different browsing contexts (tabs, windows, iframes) of the same origin, functioning as a message bus with pub/sub features. By creating a BroadcastChannel object, the contexts are able to receive messages that are posted to the channel. The contexts are subscribed to the channel by creating their own channel instance with the same name, establishing a bi-directional communication between them.

This makes the API a simple and powerful solution for easily detecting user actions and data synchronization between contexts by providing one-to-many communication. In my case, it was a great choice for detecting a log out in one tab and synchronizing the same action in other tabs. But how simple is the setup?

Setting up the communication channel.

Let’s go through the steps necessary to create the channel of communication by taking a closer look at an example like logging out all browser contexts in a React application.

  1. Create the broadcast channel object within the context

The contexts join the broadcast channel by creating an object, whose constructor takes the channel name as an argument. Create an instance in a utility file where it could be reused throughout out the application.

/* utils/Session.js */

import { BroadcastChannel } from 'broadcast-channel'

const logoutChannel = new BraodcastChannel('logout')

2. Sending a message

To send a message to the channel, it is as simple as calling postMessage on the created channel object, which takes a broad variety of arguments supported by the structured clone algorithm. In the case of our logout, it was enough to pass a string. A method logoutSession was created in order to post a message to the logout channel.

An important note to mention, a message won’t broadcast to itself. Therefore, as we can see here in our logoutSession method, after postMessage is called, we perform logout actions for the publishing context.

/* utils/Session.js */

import { BroadcastChannel } from 'broadcast-channel'

const logoutChannel = new BroadcastChannel('logout')

export const logoutSession = () {
logoutChannel.postMessage('logout_session')

// Perform actions here complete logging out, such as ending user session
// and redirecting to the login page
}

As shown below, the connection to the channel can now be used in our Logout component, posting the message for other contexts to receive.

import React from "react"
import { logoutSession } from 'utils/endSession'

const Logout = () => (
<button onClick={logoutSession}>Logout</button>
)

3. Receiving a message

When a message is posted, the message is dispatched to each BroadcastChannel object connected to the named channel. In order for the message to be received, the onmessage event handler must be set on the channel instance. Here we create the logoutAllTabSessionsListener , which can be placed in a common component throughout all contexts allowing them to receive the messages.

/* utils/Session.js */

import { BroadcastChannel } from 'broadcast-channel'

const logoutChannel = new BraodcastChannel('logout')

export const logoutSession = () {
logoutChannel.postMessage('logout_session')

// Perform actions here that end session, such ending user session
// and redirecting to the login page
}

export const logoutAllTabSessionsListener = () => {
logoutChannel.onmessage = () => {
logoutSession()
logoutChannel.close()
}
}

Below, for example, I added a listener to the main app component, to be established on each context. Just like that, in a few steps, synchronizing contexts can be done and logging out becomes more secure.

/* App.js */

const App = () => {
...

useEffect(() => {
logoutAllTabSessionsListener()
})

...
}

Final Broadcast.

The Broadcast Channel API is a simple yet powerful interface, created with an easy one-to-many communication in mind, making communication for contexts within the same origin accessible. I hope when you are in need of keeping your browser data in sync and secure, I’ve helped to add a useful tool in your arsenal.

Happy coding, happy exploring!

--

--

Michael P. Dumalag
Red Squirrel

Jiu Jitsu and Muay Thai fighting, Budding Web Developer with love for the front to back-end.