BroadcastChannel
是一种用于在同一来源(同一协议、主机名和端口号)下不同浏览器上下文(如标签页、iframe、Worker、Service Worker)之间进行消息广播的 API。它提供了一种简便、可靠的方法来实现跨上下文的实时通讯。
BroadcastChannel 的基本概念
- 广播频道:
BroadcastChannel
创建的实例代表一个特定的广播频道,所有监听该频道的上下文都能接收该频道发送的消息。 - 消息广播:通过
postMessage
方法发送消息,所有监听该频道的上下文都会收到消息。 - 消息监听:通过
onmessage
事件处理器接收和处理来自该频道的消息。
基本用法
1. 创建频道
在多个上下文中使用相同的频道名称创建 BroadcastChannel
实例。
const channel = new BroadcastChannel('my_channel');
2. 发送消息
在任意一个上下文中,通过 postMessage
方法向频道发送消息。
channel.postMessage('Hello from one context');
3. 接收消息
在其他上下文中,通过监听 onmessage
事件接收消息。
channel.onmessage = (event) => {
console.log('Received message:', event.data);
};
工作流程图
以下是 BroadcastChannel
实现不同标签页之间通讯的工作流程图:
┌──────────────────────┐ ┌──────────────────────┐
│ Page A │ │ Page B │
│ │ │ │
│ BroadcastChannel │ │ BroadcastChannel │
│ 'my_channel' │ │ 'my_channel' │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ channel.postMessage │ │ │
│ ('Hello from A') │────────────────│ channel.onmessage │
│ │ │ event.data === │
│ │ │ 'Hello from A' │
│ │ │ │
└──────────────────────┘ └──────────────────────┘
示例代码
标签页 A 的代码
<!DOCTYPE html>
<html>
<head>
<title>Page A</title>
</head>
<body>
<button onclick="sendMessage()">Send Message</button>
<script>
const channel = new BroadcastChannel('my_channel');
function sendMessage() {
channel.postMessage('Hello from Page A');
}
</script>
</body>
</html>
标签页 B 的代码
<!DOCTYPE html>
<html>
<head>
<title>Page B</title>
</head>
<body>
<script>
const channel = new BroadcastChannel('my_channel');
channel.onmessage = (event) => {
console.log('Received message in Page B:', event.data);
};
</script>
</body>
</html>
BroadcastChannel 的特点和优缺点
特点
- 实时通讯:能够在不同浏览器上下文之间进行实时消息传递。
- 简洁易用:API 简单明了,只需少量代码即可实现。
- 同源策略:确保安全性,只有同源的上下文才能相互通讯。
优点
- 实时性好:消息几乎是实时传递的,适用于需要即时通讯的场景。
- 使用简单:不需要复杂的设置,易于实现和维护。
- 跨上下文:支持标签页、iframe、Worker 和 Service Worker 之间的通讯,适用范围广。
缺点
- 不持久化:消息不会持久化,页面刷新或关闭后,之前的消息无法再获取。
- 同源限制:只能在同源上下文之间通讯,不同来源无法相互通讯。
实际应用场景
1. 用户登录状态同步
当用户在一个标签页中登录或注销,其他打开同一应用的标签页需要同步登录状态。
// 标签页 A 中用户登录
const authChannel = new BroadcastChannel('auth_channel');
authChannel.postMessage('User logged in');
// 其他标签页中监听登录状态变化
authChannel.onmessage = (event) => {
if (event.data === 'User logged in') {
// 同步用户登录状态
}
};
2. 实时数据更新
在一个标签页中更新数据,其他标签页需要实时显示更新结果,例如股票行情、实时聊天消息等。
// 标签页 A 中更新数据
const dataChannel = new BroadcastChannel('data_channel');
dataChannel.postMessage({ type: 'update', data: 'New data' });
// 其他标签页中监听数据更新
dataChannel.onmessage = (event) => {
if (event.data.type === 'update') {
console.log('Received data update:', event.data.data);
// 更新界面显示
}
};
3. 多标签页协同工作
用户在多个标签页中打开同一个应用,需要各标签页协同工作。例如,在一个标签页中填写表单,另一个标签页显示表单预览。
// 标签页 A 中填写表单并广播数据
const formChannel = new BroadcastChannel('form_channel');
document.getElementById('formInput').addEventListener('input', (event) => {
formChannel.postMessage({ type: 'form_update', value: event.target.value });
});
// 标签页 B 中接收表单数据并显示预览
formChannel.onmessage = (event) => {
if (event.data.type === 'form_update') {
document.getElementById('formPreview').innerText = event.data.value;
}
};
总结
BroadcastChannel
提供了一种简单而强大的方法,用于在同源的不同浏览器上下文之间进行实时通讯。它特别适合需要即时同步数据的应用场景,如用户登录状态同步、实时数据更新和多标签页协同工作。通过掌握 BroadcastChannel
的使用方法,开发者可以大大提升 web 应用的用户体验和功能。