Tutorial

How to use the BroadcastChannel API in JavaScript

Published on January 13, 2020
author

Jack Misteli

How to use the BroadcastChannel API in JavaScript

The BroadcastChannel API is a new web platform API that lets you communicate between different windows/tabs/iframes of the same origin. Using BroadcastChannel may sound fancy and daunting but it is super easy and useful.

Why use the BroadcastChannel API

Try to log into one of your favorite websites (I tried it on youtube.com). Then, open in a separate tab the same website. Normally you will be logged into both pages. Then log out on one of your tabs. On most sites, it will look like you are logged in one page and logged off the other.

Your windows are in different states: logged-in vs logged-out. That’s not great and if you are a maniac tabber (like me) it can lead to some confusion.

This can even be a security issue. Imagine your user is in a coffee shop using the company dashboard. He logs off to take a toilet break and leaves the computer on. If the application was opened in multiple tabs one could access the data available in the other tabs (on screen or maybe some JWT token).

BroadcastChannel API Code

Here’s a very simple example that you can copy paste in a local HTML file:

<!DOCTYPE html>

<body>
  <!-- The title will change to greet the user -->
  <h1 id="title">Hey</h1>
  <input id="name-field" placeholder="Enter Your Name"/>
</body>

<script>

var bc = new BroadcastChannel('gator_channel');

(()=>{
  const title = document.getElementById('title');
  const nameField = document.getElementById('name-field');
  const setTitle = (userName) => {
    title.innerHTML = 'Hey ' + userName;
  }

  bc.onmessage = (messageEvent) => {
    // If our broadcast message is 'update_title' then get the new title from localStorage
    if (messageEvent.data === 'update_title') {
      // localStorage is domain specific so when it changes in one window it changes in the other
      setTitle(localStorage.getItem('title'));
    }
  }

  // When the page loads check if the title is in our localStorage
  if (localStorage.getItem('title')) {
    setTitle(localStorage.getItem('title'));
  } else {
    setTitle('please tell us your name');
  }

  nameField.onchange = (e) => {
    const inputValue = e.target.value;
    // In the localStorage we set title to the user's input
    localStorage.setItem('title', inputValue);
    // Update the title on the current page 
    setTitle(inputValue);
    // Tell the other pages to update the title
    bc.postMessage('update_title');
  }
})()
</script>

This page has a title and an input. When the user enters her name in the input we store the name in the local storage under the key userName. Then, we set the title of our application to 'Hey' + userName. So if the user’s name is Sarah the page will show “Hey Sarah”.

If we didn’t have a BroadcastChannel when the user enters her name in one window it wouldn’t update the other window. Without the broadcast channel in our code, the user would have to refresh the second window to update the title.

So in our first line, we create a BroadcastChannel called “gator_channel”. We then create a message receiver using the onmessage method. We set onmessage to a function that takes one argument (aka an event message). Then, in our code, we check that the name of the message is update_title. If so, we extract the user name from the local storage.

Whenever we call postMessage on the broadcast channel, it will call onmessage in the other windows. So if I input Jack in window 1, then window 1 will call bc.postMessage('updated_title'). This will activate onmessage on window 2 and any other window opened on the same origin.

Where it Will Work

Unlike other APIs such as window.postMessage, you don’t need to know anything about the other windows or tabs opened. The Broadcast Channel will work on any tab or window which is in the same origin (same scheme, host and port).

This means that you can broadcast messages from https://alligator.io/ to https://alligator.io/js/broadcast-channels. All you need is to have a BroadcastChanel object on both pages using the same channel name:

const bc = new BroadcastChannel('alligator_channel');
bc.onmessage = (eventMessage) => {
  // do something different on each page
}

If the hosts are different it won’t work:

If the ports are different it won’t work:

If the schemes are different it won’t work. That is similar to different ports since the standard is that http and https respectively use port 80 and 443:

Broadcast channels will not work if one of the windows is in incognito mode or across browsers (e.g. Firefox to Chrome).

Browser compatibility

According to (caniuse.com)[https://caniuse.com/#feat=broadcastchannel], the BroadcastChannel API is available to about 75.6% of users. Safari and Internet Explorer don’t have any support for it yet.

To my knowledge, the most popular polyfill is this one. You can use it almost exactly like the BroadcastChannel API. If it detects that the BroadcastChannel API is available it will use it automatically for faster results. Otherwise, it will use IndexedDB or LocalStorage.

What Messages Can We Pass?

You can pass anything that can be cloned using the structured clone algorithm. That includes almost everything except symbols:

  • All primitive types except symbols (Boolean, Null, Undefined, Number, BigInt, String)
  • Boolean and String objects
  • Dates
  • Regular Expressions
  • Blobs
  • Files, FileLists
  • ArrayBuffers, ArrayBufferViews
  • ImageBitmaps, ImageDatas
  • Arrays, Objects, Maps and Sets

If you try sending something like a Symbol, you will get an error on the sending side.


Let’s update our code and use objects instead of strings.

  bc.onmessage = (messageEvent) => {
    const data = messageEvent.data
    // If our broadcast message is 'update_title' then get the new title from localStorage
    switch (data.type) {
      case 'update_title':
        if (data.title){
          setTitle(data.title);
        }
        else
          setTitle(localStorage.getItem('title'));
        break
      default:
        console.log('we received a message')
    }
  };
  // ... Skipping Code
  bc.postMessage({type: 'update_title', title: inputValue});

Things You Can Do with Broadcast Channels

There are many things we can imagine. The most obvious use case is to share states. For example, if you use something like Flux or Redux to manage your state, you can broadcast a message so that your store remains the same across tabs. We can also imagine building something similar for state machines.

We saw that we can also send large files in different formats. We might be able to save some bandwidth by sharing large files such as images across tabs.

Closing a Broadcast Channel

Closing a broadcast channel is super easy. You simply have to run the close method on your broadcast channel:

bc.close()

You might want to close or open channels depending on the state of your application. For instance, when you are logged-in you might have a specific channel to share your application’s state. You might want to close that channel when you log out.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Jack Misteli

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more