DEV Community

Cover image for Exploring the Broadcast Channel API
Bernardo Pacheco
Bernardo Pacheco

Posted on

Exploring the Broadcast Channel API

You know those digital menu boards that you see at quick service restaurants? Well, last year I got to work on one of those.

Ok, but what does that have to do with the Broadcast Channel API?

A little bit of background

In our particular case, the menu board is a React web app running in a Chromebox at the restaurant. It supports two displays and we control which page of the menu it shows based on the URL route.

Two Browser windows showing different menu pages

One of the requirements was that we needed to animate certain elements in the menu, but there was a catch. The animations had to be synchronized across the displays. We couldn't just fire up the animation loop whenever we wanted. We needed a way for the two pages to communicate with each other to start their timers at the same time.

Enter the Broadcast Channel API.

What is the Broadcast Channel API?

It is a Web API that allows basic communication between browsing contexts (i.e. windows, tabs, iframes, webviews) on the same origin.

Two browser windows communicating through a broadcast channel

You start by creating a BroadcastChannel object and giving it a name. If a channel with the same name already exists, it will join the channel instead.

const channel = new BroadcastChannel("channel_name")
Enter fullscreen mode Exit fullscreen mode

To send a message you call the postMessage() method on the created object, which takes any object as an argument.

channel.postMessage("is this thing on?")
Enter fullscreen mode Exit fullscreen mode

This will dispatch a message event to each of the contexts that have joined the channel. We can then run a function for this event with the onmessage event handler.

channel.onmessage = ev => {
  console.log(ev.data)
}
// is this thing on?
Enter fullscreen mode Exit fullscreen mode

To disconnect from the channel you call the close() method on the object.

channel.close()
Enter fullscreen mode Exit fullscreen mode

Back to our app

We were able to leverage this API to communicate back and forth between the two displays and make sure they start their animation loop exactly at the same time. Keep in mind that each display "boots up" independently at slightly different times, so we need some negotiation up front to know when both of them are ready.

The basic logic looks something like this:

/**
 * In this example I will refer to the first display to finish 
 * booting up as "display 1". The second one to be ready will
 * be "display 2".
 */

// display 1 creates the channel; display 2 joins it
const syncChannel = new BroadcastChannel("animation-sync")

syncChannel.onmessage = ({ data }) => {
  switch (data.type) {
    // display 1 receives the "READY" message from display 2
    // and posts a message to start setting things up
    case "READY": {
      syncChannel.postMessage({ type: "START" })
      break
    }
    // display 2 receives the "START" message
    case "START": {
      // record the current time (just to be safe we pad it 5s
      // to allow display 1 to receive the next message)
      const syncTime = new Date().getTime() + 5000

      // outside function that schedules the animations
      scheduleAnimations(syncTime)

      // send "SYNC" message to display 1 with the syncTime      
      syncChannel.postMessage({ type: "SYNC", syncTime })
      break
    }
    // display 1 receives the "SYNC" message with the syncTime
    case "SYNC": {
      scheduleAnimations(data.syncTime)
      break
    }
    default:
      break
  }
}

// display 2 sends the "READY" message to display 1
animationSyncChannel.postMessage({ type: "READY" })
Enter fullscreen mode Exit fullscreen mode

Play with it

I made a simplified demo of this in Codesandbox. And here's a short preview of it:

Animated gif of two browser windows showing a synchronized timer

Pretty cool, right?

Caveat

Not every browser supports this natively. Fortunately, there's a npm package called broadcast-channel that has the same API and uses the native implementation in browsers that support it. Plus, it allows you to use it in Node too!


Cover photo by Prince Abid

Top comments (4)

Collapse
 
abdisalan_js profile image
Abdisalan • Edited

This is awesome! I might try to make a game that goes across multiple screens ๐Ÿ˜

Thanks for the clear explanation!

Collapse
 
bernardop profile image
Bernardo Pacheco

Glad to hear it was useful! That sounds like a great idea, I'd love to see it if you do ๐Ÿ‘

Collapse
 
wobsoriano profile image
Robert

Nice one! I'm using this API for our Single Sign-On implementation.

Collapse
 
bernardop profile image
Bernardo Pacheco

Thanks! And yes, lots of cool use cases for it ๐Ÿ˜€