ACA Blog

ACA Blog


July 2020
M T W T F S S
« Jun    
 12345
6789101112
13141516171819
20212223242526
2728293031  

Categories


How to use the BroadcastChannel API with Angular

Davy Steegen and Tim Van LaerDavy Steegen and Tim Van Laer

Have you ever heard of the BroadcastChannel API? We hadn’t either just a couple of weeks ago. We happened to stumble upon it after looking for a solutions that allowed us to communicate between different browser windows of the same origin. In this blog post, we’ll discuss the API itself and teach you how to use the BroadcastChannel API within an Angular application.

The BroadcastChannel API

Imagine you opened a web page in multiple tabs, and you want to communicate between these tabs to keep them up-to-date. How would you even start to do that? After some digging around the internet, we came across the BroadcastChannel API that is implemented directly in web browsers.

It turns out that this API has already been available since 2015. Mozilla Firefox 38 was the first browser to adopt the specification. Over the course of the next few years, other browsers followed Mozilla’s example.

Check out the demo below to see an example of what can be done by utilizing this technology.

How to use the BroadcastChannel API with Angular

Albeit a very simple demo, it nevertheless shows the true power of the BroadcastChannel API. In this example, the counter is kept in sync between the two windows. It may not be your typical real world example, but you could use the API to:

The BroadcastChannel is basically an event bus where you have a producer and one or more consumers of the event:

How to use the BroadcastChannel API with Angular

How to set up a BroadcastChannel

Creating a BroadcastChannel

Creating a BroadcastChannel is very simple. It doesn’t require any libraries to be imported in your code. You just need to invoke the constructor with a String that contains the name of the channel to be created.

Sending a message

Now that we’ve set up a channel, we can use it to post messages. Posting a message can be done by calling the postMessage on the BroadcastChannel that you created earlier.

The postMessage can take all kinds of objects as message. You can basically send anything that you want, as long as the consumer knows how to handle the receiving objects. However, it’s good practice to have a field on your messages that describes the type of message it is. This makes it easier to subscribe to messages of a specific type instead of having a BroadcastChannel per type of message.

Receiving a message

On the consumer side, you’ll need to create a BroadcastChannel with the same name as on the producer side. If the names do not match, you (obviously) won’t receive any messages. Next, you need to implement the onmessage callback.

The BroadcastChannel that posts a message won’t receive the message itself, even if it has a listener registered. However, if you create a separate BroadcastChannel instance for posting and consuming messages, the browser window that posted the message will receive the message. Most likely, that’s not something you want. To avoid this, it is best practice to create a singleton instance per BroadcastChannel.

Creating a reusable BroadcastService

You don’t want to reference the BroadcastChannel API everywhere in you code where you need to produce/consume messages. Instead, let’s create a reusable service that encapsulates the logic. That way, if you ever want to replace the BroadcastChannel with another API, you only have to update one service.

In this particular service, we made good use of RxJS Observables. Pay close attention to the messagesOfType function: in this case, we used the standard RxJS filter operator to only return the messages that match the provided type. Nice and simple!

The service is almost ready for use in your Angular application. There is only one more challenge that you’ll have to face.

Running inside the Angular Zone

If you’ve been using Angular for some time, you’ll probably know about the Angular Zone. Code that runs inside the Angular Zone will automatically trigger the change detection. 

The service above doesn’t run Angular’s zone, since it uses an API that does not hook into Angular. If it receives a message and updates the internal state of a component, Angular is not immediately aware of this. That means that you don’t immediately see any changes reflected in the browser. Only after the next change detection is triggered, will the results be visible inside the browser.

To work around this issue, you can create a custom RxJS OperatorFunction. The sole purpose of the OperatorFunction is to make sure that every life cycle hook of an Observable is running inside the Angular’s Zone.

NgZone is an object provided by Angular that you can use to programmatically run code inside Angular’s zone. The only thing that remains is to use the above OperatorFunction in our BroadcastService.

After updating the service, changes will be visible immediately upon receiving messages.

Injecting the service

You can use Angular’s InjectionToken to create a singleton instance of the service. Declare the InjectionToken:

Inject the service via the InjectionToken:

Is the BroadcastChannel API supported everywhere?

You have to keep the following in mind when using the BroadcastService. It’ll only work when

All modern browsers support the BroadcastChannel API, except for Safari and Internet Explorer 11 (and below). For a full list of compatible browsers, check out Caniuse.

If you need to implement a similar solution in non-supported browsers, you can use the browser’s LocalStorage instead.

Takeaway

In this blog post, we briefly described how to make use of the browsers BroadcastChannel API inside an Angular application. We also looked at a solution on how the API can be hooked into Angular’s Zone. You can find the full code of the demo on Stackblitz. Moreover, you can consult the BroadcastChannel API documentation on MDN Web Docs.

If you have any questions, comment below and we’ll get back to you ASAP!


In search of more software development tips? Try these:

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments