BroadcastChannel,就字面意思来言,叫做“广播频道”,官方文档说,该API是用于同源不同页面之间完成通信的功能。

1. 概况

它与window.postMessage的区别就是,BroadcastChannel只能用于同源的页面之间进行通信,而window.postMessage却可以用于任何的页面之间,或者这么说吧,BroadcastChannel可以认为是window.postMessage的一个实例,它承担了window.postMessage的一个方面的功能。

基于BroadcastChannel的同源策略,那么它就有个问题是,它无法完成跨域的数据传输了,跨域的情况,我们还是安安稳稳的使用window.postMessage来处理吧。

在进行说明之前,我们首先来看一下,BroadcastChannel的浏览器支持情况吧,这个才是每个前端开发者们,最关心的问题嘛,caniuse BroadcastChannel

2. 初始化

BroadcastChannel是一个构造函数,它的初始化方法非常简单:

var bc = new BroadcastChannel('test_channel');

是的,它只需要一个参数,就是一个字符串,也就是要连接到的频道名称。

既然这个API的名字叫做Broadcast,广播,那么我们可以理解它必然有一个广播台,所有的广播实例,都会接入这个广播台(中介者模式中的控制中心),所以,只要在初始化实例时,传入的name值是相同名称的,就会被接入到一个相同的广播频道中。

3. 接收消息

有一些话,是这么说的:兵马未动 粮草先行;工欲善其事,必先利其器等。

对于消息系统来说,完成消息通信的基础,就是你首先要能接收消息,所以这里我们就先看看,如何接收消息,假设我们创建的实例变量为:bc。那么就可以通过如下的方法接收消息。

bc.onmessage = function(ev){
console.log(ev);
}

其实质是,这个就等于给DOM元素添加了一个onmessage事件,当接收到其他同源页面相同频道发送的消息时,会触发该事件。

既然类似于一个DOM的事件,那么回调函数的中的ev变量,我们也就大概能知道了。它是一个event的对象,只是该event不是我们经常用到的MouseEventKeyboardEventTouchEvent这样我们最常碰到的实例,而是来自MessageEvent的实例,但不管如何这些事件类型的构造函数,都是继承自Event,所以很多东西也都是我们最常遇到的,比如看看下面的结构,是否觉得很熟悉:

{
bubbles : false,
cancelBubble : false
cancelable : false
currentTarget : BroadcastChannel {name: "test_channel", onmessageerror: null, onmessage: ƒ}
data : ""
srcElement : BroadcastChannel {name: "test_channel", onmessageerror: null, onmessage: ƒ}
target : BroadcastChannel {name: "test_channel", onmessageerror: null, onmessage: ƒ}
type:"message"
}

只是有些区别的是,这里的currentTargetsrcElementtarget都不是DOM元素,而是我们刚才定义的实例。

当然,BroadcastChannel继承自EventTarget,所以我们也可以用以下的方法,来接收这个事件:

bc.addEventListener("message",function(ev){
wrapper.append("<p>2接收:"+ev.data+"</p>");
});

到这里,是不是想到了在刚学习JS时,绑定事件的三种方式呢?没错,这里少了一种,不能直接在DOM元素上绑定,因为没有直接对于的DOM元素啊。

至于上述两种绑定事件的方法,它们的好处,坏处,区别,我姑且认为,看这篇文章的人都是懂得了,这里就不再赘述。

4. 发送消息

可以接收消息了,接下来就可以看看,发送消息的了,发送消息就变得简单了很多。

bc.postMessage(data);

直接使用方面的postMessage就可以直接发送data数据到bc所在的频道,所有接入该频道的页面,都能收到该消息。

至于data的数据类型,官方文档中说是支持任意的JS数据类型,但是在不同的浏览器厂商来说,这个实现就有些许差异,有些浏览器厂商可能只是支持传输String类型的数据,所以使用的时候,尽量还是传输String类型的吧,如果是对象的话,那么进行一下JSON.stringify(data)

发送消息的方法,只要这一种方式而已,虽然BroadcastChannel也是属于事件系统的一种,按理说也可以直接使用dispatchEvent方法,来触发postMessage的动作,但是,我自己尝试了一下,发现并不行,无法发送到频道中心,只能在自己的页面接收到自己也没发送的消息,所以就失去了原有的意义,没有再多花时间,去研究是否可以使用dispatchEvent完全实现bc.postMessage的功能,所以,就默认只是记住postMessage方法吧,简单。

5. 关闭

在初始化实例的时候,是接入广播通道的,而现在就来关闭这个连接吧,简单的使用close方法既可以,不多说了

bc.close();

6. 其他

BroadcastChannel的实例中,还有另外一个属性,在我看来,目前是没有什么用处的属性,bc.name,其实就是你连接的广播频道的名称,比如我们这里的就是:bc.name = "test_channel",为什么说没有用呢,因为这个属性是只读的,不能通过修改这个name的属性值,直接进行切换频道(我只是这么想想)。

05-04 02:59