浏览器中的跨页面通信之Broadcast Channel、SharedWorker

浏览器中的跨页面通信之Broadcast Channel、SharedWorker

Broadcast Channel

听到Broadcast Channel这个概念,在React的源码中,还有一个类似的概念MessageChannel(为了解决requestIdleCallback兼容性问题)

好文推荐:https://blog.csdn.net/weixin_44273311/article/details/136342234

好文推荐:https://blog.csdn.net/super_ying123/article/details/136284917

MD文档:https://developer.mozilla.org/zh-CN/docs/Web/API/BroadcastChannel

Broadcast Channel 是什么

  • BroadcastChannel 允许在相同的源(通常页面来自相同的网站)在浏览器上下文(windows,tabs,frames或者iframes)之间进行简单的通信。

    image-20240903144826507

  • Broadcast Channel 与 window.postMessage区别

    • BroadcastChannel,叫做“广播频道”,官方文档说,该API是用于同源不同页面之间完成通信的功能。
    • BroadcastChannel只能用于同源的页面之间进行通信,而window.postMessage却可以用于任何的页面之间
    • 基于BroadcastChannel的同源策略,它无法完成跨域的数据传输,跨域的情况,我们还是使用window.postMessage来处理

Broadcast Channel使用

用构造函数创建一个实例
const bc = new BroadcastChannel('test_channel');

test_channel 参数用来指定channel的名称,用以标识这个 channel,在其他页面,可以通过传入相同的 name 来使用同一个广播频道,连接到相同名称的BroadcastChannel,可以监听到这个channel分发的消息。用 MDN 上的话来解释就是:

There is one single channel with this name for all browsing contexts with the same origin.

该 name 值可以通过实例的 bc.name属性获得

监听消息
  • 广播创建完成后,就可以在页面监听广播的消息

    bc.onmessage = function(e) {
        console.log('receive:', e.data);
    }; // 对于错误也可以绑定监听:
    bc.onmessageerror = function(e) {
        console.warn('error:', e);
    };
    
  • 除了为.onmessage赋值这种方式,也可以使用addEventListener来添加'message'监听

发送消息
  • 广播实例也有一个对应的postMessage用于发送消息

    bc.postMessage('hello')
    
关闭广播监听
  • 取消当前页面的广播监听的方式

    • 取消或者修改相应的'message'事件监听
    • 使用 Broadcast Channel 实例为我们提供的close方法:bc.close();
  • 两者是有区别的

    • 取消'message'监听只是让页面不对广播消息进行响应,Broadcast Channel 仍然存在

    • 而调用close方法这会切断与 Broadcast Channel 的连接,浏览器才能够尝试回收该对象,因为此时浏览器才会知道用户已经不需要使用广播频道了

    • 在关闭后调用postMessage会出现如下报错

      image-20240903145542829

    • 如果之后又再需要广播,则可以重新创建一个相同 name 的 Broadcast Channel

兼容性

  • BroadcastChannel 是一个非常简单的 API ,内部包含了跨上下文同源通信的接口。它没有定义消息传输协议,故不同上下文中的不同文档需要自己实现。目前来看兼容性方面也基本没有问题

    image-20240903145726516

SharedWorker

  • JavaScript是单线程的,单线程有好处也有坏处。为了弥补JS单线程的坏处,webWorker随之被提出,它可以为JS创造多线程环境。如果还不了解webWorker的可以去官网初步了解一下。
  • sharedWorker就是webWorker中的一种,它可以由所有同源页面共享,利用这个特性,我们就可以使用它来进行多标签页之前的通信

SharedWorker特点

  • 跨域不共享,即多个标签页不能跨域
  • 使用port发送和接收消息
  • 如果url相同,且是同一个js,那么只会创建一个sharedWorker,多个页面共享这个sharedWorker

其实它和我们的webSocket实现多页面通讯的原理很类似,都是发送数据和接收数据这样的步骤,shardWorker就好比我们的webSocket服务器

SharedWorker使用

  • 好文推荐:https://blog.csdn.net/zxcvb0825/article/details/135057537
  • MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/API/SharedWorker

worker.js

// worker.js
const set = new Set()
onconnect = event => {
  const port = event.ports[0]
  set.add(port)


  // 接收信息
  port.onmessage = e => {
    // 广播信息
    set.forEach(p => {
      p.postMessage(e.data)
    })
  }


  // 发送信息
  port.postMessage("worker广播信息")
}

pageA.html

<script>
  const worker = new SharedWorker('./worker.js')
  worker.port.onmessage = e => {
    console.info("pageA收到消息", e.data)
  }
</script>

pageB.html

<script>
  const worker = new SharedWorker('./worker.js')
  let btnB = document.getElementById("btnB");
  let num = 0;
  btnB.addEventListener("click", () => {
    worker.port.postMessage(`客户端B发送的消息:${num++}`)
  })
</script>
  • 上面的代码就是一个最简单的sharedWorker的应用,我们在pageA页面中初始化了sharedWorker,并且设置了接收消息的监听函

    数,当sharedWorker初始化完成之后,pageA便会接收到一条消息,如下图

img

  • 然后我们在pageB中同样初始化了sharedWorker的示例,点击按钮广播消息,此时pageA便可以收到消息

pageA输出结果

img

调试sharedWorker

  • 我们如何查看当前是运行的哪个sharedWorker呢?可以在浏览时输入:chrome://inspect。
  • 找到sharedWorker选项,就可以看到运行的sharedWorker,如下图

img

兼容性

https://caniuse.com/?search=SharedWorker

image-20240903150823127

  • 调试不太方便、兼容性不太好,具体使用根据具体情况选择
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值