最近在看微服务方面的东西,看到关于 多个微服务页面间通信和数据共享的解决方案,发现了一些比较陌生的 API
,说是陌生其实专门拿出来也能说出个所以然来,也知道是个什么东西,但就是不熟练,凭空想的话就很难能想到,看了一下觉得有些门道,于是索性扩展开来整理了一下
BroadcastChannel
Broadcast
也是“广播”的意思,将信号广播出去,允许其他人接听。
此 API
允许同一原始域和用户代理下的所有窗口、iFrames
等进行交互,属于 同源通信。也就是说,如果用户打开了同一个网站的的两个标签窗口,如果网站内容发生了变化,那么两个窗口会同时得到更新通知。
使用的场景,如,用户同时依次打开某个网站的几个页面,然后在其中一个页面 A
进行登录操作,那么其他的页面就可以通过 BroadcastChannel
收到来自页面 A
的登录状态,从而能够完成多个页面自动同步登录状态的目的。
// A页面向外广播信号
// 创建句柄
const cast = new BroadcastChannel('mychannel')
// data 可以是任何 JS数据类型
const data = 'I\'m from Page A'
// 广播信号
cast.postMessage(data)
// 关闭连接
cast.close()
// B页面监听同源下所有页面发送出的“广播”
// BroadcastChannel的参数,即channel号必须与想要监听的广播源相同,这里是 mychannel
const cast = new BroadcastChannel('mychannel')
// 接收信号
cast.onmessage = function (e) {
console.log(e.data) // => I'm from Page A
}
// 关闭连接
cast.close()
用起来很顺手,也没什么复杂的道道,BroadcastChannel
的初始化参数 channel
,可以看做是一个广播频道,只要同源下加入这个频道的页面,都能够互相收发信号进行通信,但是浏览器支持度很不乐观,而且一直也都没什么进展,总感觉将来某天就要嗝屁了
postMessage
otherWindow.postMessage(message, targetOrigin, [transfer]);
相比于 BroadcastChannel
来说, postMessage
明显幸福多了,postMessage
支持 跨域通信,浏览器支持度也秒杀 BroadcastChannel
,达到了完全可在生产环境使用的地步,说明浏览器厂商对这个还是很热衷的。资本推动技术,没毛病
A
页面通过 window.open
获得 B
页面的句柄,向 B
页面发送信号,并监听 B
页面回传回来的信号
<!-- A页面 -->
<div id="msg"></div>
<script>
window.onload = () => {
// 获取句柄
var opener = window.open('http://127.0.0.1:9001/b.html')
// setTimeout 是为了等到真正获取到 opener的句柄再发送数据
setTimeout(() => {
// 只对 域名为 http://127.0.0.1:9001的页面发送数据信号
opener.postMessage('red', 'http://127.0.0.1:9001');
}, 0)
// 监听从句柄页面发送回来的数据信号
window.addEventListener('message', event => {
if(event.origin === 'http://127.0.0.1:9001'){
document.getElementById('msg').innerHTML = event.data
}
})
}
</script>
B
页面接收 A
页面的信号,并通过事件句柄反向对 A
页面发送数据信号
<div id="box">color from a.html</div>
<script type="text/javascript">
window.addEventListener('message', event => {
// 通过origin属性判断消息来源地址
// 只有当数据信号来源于 http://127.0.0.1:9001的服务器才接收
if(event.origin === 'http://127.0.0.1:9001'){
// 获取信息员的数据信号
document.getElementById('box').style.color = event.data
// 通过 event.source向信号源反向发送数据
event.source.