当前位置: 首页 > 科技观察

JavaScript是如何实现同源通信的?

时间:2023-03-11 21:35:20 科技观察

在日常工作中,您可能会遇到同源页面之间通信的场景。对于这种场景,我们可以使用localStorage和storageevents来解决同源页面之间的通信问题。另外,我们也可以使用BroadcastChannelAPI来解决这个问题。接下来阿宝哥就带大家认识一下BroadcastChannelAPI。一、BroadcastChannelAPI简介BroadcastChannelAPI可以实现同一源下不同窗口、标签页或iframe中浏览器上下文之间的简单通信。通过创建一个侦听频道的BroadcastChannel对象,您可以接收发送到该频道的所有消息。(图片来源-https://developer.mozilla.org/zh-CN/docs/Web/API/Broadcast_Channel_API)了解了BroadcastChannelAPI的作用后,我们来看看如何使用它://创建一个forBroadcastcommunicationchannelconstchannel=newBroadcastChannel('my_bus');//在my_bus频道上发送消息.postMessage('大家好,我是阿宝哥');//在my_bus频道上收听消息channel.onmessage=function(e){console.log('Receivedmessage:',e.data);};//关闭通道channel.close();通过观察上面的例子,我们可以发现BroadcastChannelAPI的使用还是非常简单的。该API除了支持发送字符串外,还可以发送其他对象,如Blob、File、ArrayBuffer、Array等对象。另外需要注意的是,在实际项目中,我们还需要考虑它的兼容性:(图片来源-https://caniuse.com/?search=Broadcast%20Channel%20API)从上图可以看出,IE11及以下版本不支持BroadcastChannelAPI,那么可以考虑使用现成的broadcast-channel-polyfill或者基于localStorage和storageevents实现。2.BroadcastChannelAPI的应用场景使用BroadcastChannelAPI,我们可以轻松实现同源页面之间的一对多通信。该API的一些使用场景如下:实现同源页面之间的数据同步;监听其他Tab页的用户操作;指导工人执行后台任务;了解用户何时在另一个窗口/选项卡中登录帐户。为了让大家更好的理解BroadcastChannelAPI,阿宝哥以前面两个使用场景为例,介绍一下API的具体应用。2.1实现同源页面之间的数据同步(()=>{consttitle=document.querySelector("#title");constuserName=document.querySelector("#userName");constsetTitle=(userName)=>{title.innerHTML="Hello,"+userName;};bc.onmessage=(messageEvent)=>{if(messageEvent.data==="update_title"){setTitle(localStorage.getItem("title"));}};if(localStorage.getItem("title")){setTitle(localStorage.getItem("title"));}else{setTitle("请告诉我们你的用户名");}userName.onchange=(e)=>{constinputValue=e.target.value;localStorage.setItem("title",inputValue);setTitle(inputValue);bc.postMessage("update_title");};})();在上面的例子中,我们实现了同源页面之间的数据同步。当任何打开的页面中输入框的数据发生变化时,页面中h3#title元素的内容会自动同步更新。2.2监听其他Tab页面的用户操作使用BroadcastChannelAPI,除了可以实现同源页面之间的数据同步外,我们还可以通过它来监听其他Tab页面的用户操作。例如,当用户在任意一个Tab中执行退出操作时,其他打开的Tab页面也可以自动退出,从而保证了系统的安全性。html当前状态:登录注销JSconststatus=document.querySelector("#status");constlogoutChannel=newBroadcastChannel("logout_channel");logoutChannel.onmessage=function(e){if(e.data.cmd==="logout"){doLogout();}};functionlogout(){doLogout();logoutChannel.postMessage({cmd:"注销",user:"Abaoge"});}functiondoLogout(){status.innerText="Currentstatus:Loggedout";}在上面的例子中,当用户点击注销按钮时,当前页面会执行注销操作,同时会通过logoutChannel通知其他打开的页面进行注销操作。3.广播频道API与postMessageAPI与postMessage()不同,您不再需要维护对iframe或worker的引用以与其通信:constpopup=window.open('https://another-origin.com',...);popup.postMessage('Suppopup!','https://another-origin.com');BroadcastChannelAPI只能用于实现在同源浏览器的不同窗口、标签页或iframe中浏览服务器上下文之间的简单通信。但是,postMessageAPI可用于在不同来源之间传递消息。由于消息保证来自同一来源,因此无需像使用之前那样验证消息:constiframe=document.querySelector('iframe');iframe.contentWindow.onmessage=function(e){if(e.origin!=='https://expected-origin.com'){return;}e.source.postMessage('Ack!',e.origin);};4.总结BroadcastChannelAPI是一个非常简单的API,它包含用于上下文通信的交叉接口。在支持该API的浏览器中,我们可以使用该API轻松实现同源页面之间的通信。对于不支持该API的浏览器,我们可以考虑使用localStorage和storageevents来解决同源页面之间的通信问题。5.参考资源MDN-BroadcastChannelAPIBroadcastChannelAPI:AMessageBusfortheWeb