Have you ever opened the same web app in two browser tabs and noticed that they behave like two completely separate applications?
Sometimes that’s fine.
But sometimes you want an action in one tab to be immediately reflected in the others.
You could use a server, WebSockets, polling, or even localStorage.
But for simple communication between browser tabs, JavaScript already provides a native API:
BroadcastChannel.
Let’s see how it works by building a very small counter that stays synchronized across multiple tabs.
The HTML
We only need a counter and a button:
<h2 id="counter">0</h2>
<button id="increment">+1</button>
Enter fullscreen mode Exit fullscreen mode
Nothing special so far.
Each browser tab will have its own JavaScript state:
let count = 0;
Enter fullscreen mode Exit fullscreen mode
Without any synchronization, clicking the button in one tab would only update that tab.
Let’s fix that.
Create a BroadcastChannel
First, create a channel:
const channel = new BroadcastChannel("counter");
Enter fullscreen mode Exit fullscreen mode
The string "counter" is simply the name of the channel.
Any tab from the same origin that creates a BroadcastChannel with the same name can communicate with the others.
Now let’s implement our counter.
const channel = new BroadcastChannel("counter");
let count = 0;
const counter = document.querySelector("#counter");
const button = document.querySelector("#increment");
button.onclick = () => {
count++;
counter.textContent = count;
channel.postMessage(count);
};
Enter fullscreen mode Exit fullscreen mode
Every time we click the button, we increase the counter and then send the new value through the channel:
channel.postMessage(count);
Enter fullscreen mode Exit fullscreen mode
But the other tabs still need to listen for that message.
Receive messages from other tabs
We can do that with the message event:
channel.onmessage = ({ data }) => {
count = data;
counter.textContent = count;
};
Enter fullscreen mode Exit fullscreen mode
And that’s basically the whole implementation.
Here is the complete JavaScript:
const channel = new BroadcastChannel("counter");
let count = 0;
const counter = document.querySelector("#counter");
const button = document.querySelector("#increment");
button.onclick = () => {
count++;
counter.textContent = count;
channel.postMessage(count);
};
channel.onmessage = ({ data }) => {
count = data;
counter.textContent = count;
};
Enter fullscreen mode Exit fullscreen mode
Now open the page in two browser tabs.
Click +1 in the first tab:
Tab 1 → 1
Tab 2 → 1
Enter fullscreen mode Exit fullscreen mode
Then click +1 in the second tab:
Tab 1 → 2
Tab 2 → 2
Enter fullscreen mode Exit fullscreen mode
The two tabs are now communicating directly.
No server.
No WebSocket.
No polling.
What is actually happening?
When this line runs:
channel.postMessage(count);
Enter fullscreen mode Exit fullscreen mode
the browser sends the value to the other contexts listening to the "counter" channel.
The other tab receives it here:
channel.onmessage = ({ data }) => {
// data contains the received value
};
Enter fullscreen mode Exit fullscreen mode
One important detail is that a channel does not send the message back to the same BroadcastChannel object that posted it.
That’s why we update the current tab ourselves:
counter.textContent = count;
Enter fullscreen mode Exit fullscreen mode
and use BroadcastChannel to update the other tabs.
You can send more than numbers
BroadcastChannel isn’t limited to strings or numbers.
You can send objects too:
channel.postMessage({
type: "counter-updated",
value: count
});
Enter fullscreen mode Exit fullscreen mode
And receive them normally:
channel.onmessage = ({ data }) => {
if (data.type === "counter-updated") {
count = data.value;
counter.textContent = count;
}
};
Enter fullscreen mode Exit fullscreen mode
For real applications, this approach is often better because different message types can share the same channel.
Same origin only
There is one important restriction.
BroadcastChannel works between browsing contexts that belong to the same origin.
For example, two tabs opened on:
https://example.com
Enter fullscreen mode Exit fullscreen mode
can communicate with each other.
A page on another domain cannot join that channel.
This makes BroadcastChannel useful for communication between different instances of the same web application.
When is this useful?
A synchronized counter is obviously just a demo.
In a real application, the same technique can be used to:
- refresh data after another tab modifies it
- synchronize application state
- notify tabs when cached data becomes stale
- coordinate background operations
- communicate between tabs, windows and Web Workers
For simple cross-tab communication, it can save you from building a much more complicated solution.
Closing the channel
When you no longer need the channel, you can close it:
channel.close();
Enter fullscreen mode Exit fullscreen mode
For channels that exist for the entire lifetime of a page, this may not be especially important.
But it’s useful when channels are created dynamically.
Final thought
BroadcastChannel is one of those small Web APIs that is easy to overlook.
The entire idea comes down to two operations.
Send something:
channel.postMessage(data);
Enter fullscreen mode Exit fullscreen mode
Receive something:
channel.onmessage = ({ data }) => {
// react to the message
};
Enter fullscreen mode Exit fullscreen mode
So the next time you need two tabs of the same web app to communicate, you might not need a server or WebSocket connection.
Sometimes the browser already gives you exactly what you need.
답글 남기기
댓글을 달기 위해서는 로그인해야합니다.