BroadcastChannel API是一个新的Web平台API,允许您在相同来源的不同窗口/标签/iframes之间进行通信。
为什么要使用 BroadcastChannel API
尝试登录你最喜欢的网站之一(我在youtube.com上尝试过)。然后,在单独的页面中打开相同的网站。通常你会登录到两个页面。然后登录到你的页面之一。在大多数网站上,它看起来像你在一个页面上登录,在另一个页面上登录。
你的窗口处于不同的状态:登录与退出,这不是很棒,如果你是一个疯狂的骗子(像我一样),它可能会导致一些混乱。
这甚至可能是一个安全问题. 想象你的用户是在一家咖啡店使用公司的仪表板。 他登录取厕所休息并离开计算机打开. 如果应用程序在多个卡上打开,可以访问其他卡(屏幕上或某些JWT代币)中可用的数据。
广播频道API代码
以下是一个非常简单的例子,您可以将粘贴复制到本地HTML文件中:
1<!DOCTYPE html>
2
3<body>
4 <!-- The title will change to greet the user -->
5 <h1 id="title">Hey</h1>
6 <input id="name-field" placeholder="Enter Your Name"/>
7</body>
8
9<script>
10
11var bc = new BroadcastChannel('gator_channel');
12
13(()=>{
14 const title = document.getElementById('title');
15 const nameField = document.getElementById('name-field');
16 const setTitle = (userName) => {
17 title.innerHTML = 'Hey ' + userName;
18 }
19
20 bc.onmessage = (messageEvent) => {
21 // If our broadcast message is 'update_title' then get the new title from localStorage
22 if (messageEvent.data === 'update_title') {
23 // localStorage is domain specific so when it changes in one window it changes in the other
24 setTitle(localStorage.getItem('title'));
25 }
26 }
27
28 // When the page loads check if the title is in our localStorage
29 if (localStorage.getItem('title')) {
30 setTitle(localStorage.getItem('title'));
31 } else {
32 setTitle('please tell us your name');
33 }
34
35 nameField.onchange = (e) => {
36 const inputValue = e.target.value;
37 // In the localStorage we set title to the user's input
38 localStorage.setItem('title', inputValue);
39 // Update the title on the current page
40 setTitle(inputValue);
41 // Tell the other pages to update the title
42 bc.postMessage('update_title');
43 }
44})()
45</script>
这个页面有一个标题和一个输入.当用户在输入中输入时,我们将其名称存储在本地存储中,在userName
键下。
如果我们没有一个BroadcastChannel
,当用户在一个窗口中输入她的名字时,它不会更新另一个窗口。
因此,在第一行中,我们创建了一个名为gator_channel
的BroadcastChannel
。然后我们使用onmessage
方法创建一个消息接收器。我们将onmessage
设置为一个函数,该函数需要一个参数(也称为事件消息)。
每当我们在广播频道上调用postMessage
时,它会在其他窗口中调用onmessage
。所以,如果我在窗口 1中输入Jack,那么窗口 1会调用bc.postMessage
(更新_标题)。
它将工作在哪里
與「window.postMessage」等其他 API 不同,您不需要知道其他開啟的窗口或頁面。
这意味着您可以从 https://alligator.io/
广播消息到 https://alligator.io/js/broadcast-channels
. 您所需要的只是在使用相同的频道名称的两页上有一个 BroadcastChanel
对象:
1const bc = new BroadcastChannel('alligator_channel');
2bc.onmessage = (eventMessage) => {
3 // do something different on each page
4}
如果主机不同,它不会起作用:
如果端口不同,它不会起作用:
- https://www.mkbr.io(mkbr1)* https://mkbr.io:8080(mkbr1)
这是类似于不同的端口,因为标准是 http 和 https 分别使用端口 80 和 443:
如果其中一个窗口处于匿名模式或跨浏览器(例如,Firefox到Chrome)时,广播频道将无法工作。
浏览器兼容性
根據 (caniuse.com)https://caniuse.com/#feat=broadcastchannel,BroadcastChannel API 可供大約 75.6% 的用戶使用。 Safari 和 Internet Explorer 尚未提供任何支援。
據我所知,最受歡迎的多重檔案是 這一個。你可以使用它幾乎完全像BroadcastChannel API。如果它發現BroadcastChannel API可用,它會自動使用它以獲得更快的結果。
我们可以传递哪些信息?
您可以使用结构化克隆算法传递可克隆的任何东西,其中包括除了符号之外的几乎所有东西:
所有原始类型除符号(Boolean、Null、Undefined、Number、BigInt、String)
- Boolean 和 String 对象 *日期 *常规表达式
- Blobs
- 文件、 文件列表
- ArrayBuffers、 ArrayBufferViews
- ImageBitmaps、 ImageDatas
- Arrays、 Objects、 Maps 和 Sets
如果您尝试发送象征类似的东西,则会收到发送侧的错误。
让我们更新我们的代码,使用对象而不是字符串。
1bc.onmessage = (messageEvent) => {
2 const data = messageEvent.data
3 // If our broadcast message is 'update_title' then get the new title from localStorage
4 switch (data.type) {
5 case 'update_title':
6 if (data.title){
7 setTitle(data.title);
8 }
9 else
10 setTitle(localStorage.getItem('title'));
11 break
12 default:
13 console.log('we received a message')
14 }
15 };
16 // ... Skipping Code
17 bc.postMessage({type: 'update_title', title: inputValue});
你可以用广播频道做的事情
我们可以想象很多事情。最明显的用例是共享状态.例如,如果你使用Flux或Redux来管理你的状态,你可以播放消息,以便你的商店在各个选项卡上保持相同。
我们看到,我们也可以以不同的格式发送大文件,我们可能会通过共享大文件(如图像)在卡片中节省一些带宽。
关闭一个广播频道
关闭一个广播频道非常容易. 你只需要在你的广播频道上运行关闭
方法:
1bc.close()
您可能需要关闭或打开渠道,取决于您的应用程序的状态,例如,当您登录时,您可能有一个特定的渠道来共享您的应用程序的状态。