热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

标签或窗口之间的通信

如何解决《标签或窗口之间的通信》经验,为你挑选了6个好方法。

我正在寻找一种方法,如何在浏览器中的多个选项卡或窗口之间进行通信(在同一个域上,而不是CORS),而不留痕迹.有几个解决方案:

    使用窗口对象

    的postMessage

    饼干

    localStorage的

第一个可能是最糟糕的解决方案 - 你需要从当前窗口打开一个窗口,然后只要你打开窗户就可以进行通信.如果您在任何窗口中重新加载页面,则很可能会丢失通信.

第二种方法,使用postMessage,可能启用跨源通信,但遇到与第一种方法相同的问题.您需要维护一个窗口对象.

第三种方式,使用COOKIE,在浏览器中存储一些数据,这可以有效地看起来像向同一域上的所有窗口发送消息,但问题是你永远不知道所有标签是否已经读过"消息"打扫干净.您必须实现某种超时以定期读取COOKIE.此外,您受限于最大COOKIE长度,即4KB.

使用localStorage的第四种解决方案似乎克服了COOKIE的限制,甚至可以使用事件进行监听.接受的答案中描述了如何使用它.

编辑2018:接受的答案仍然有效,但现代浏览器有一个更新的解决方案,使用BroadcastChannel.有关如何使用BroadcastChannel在选项卡之间轻松传输消息的简单示例,请参阅其他答案.



1> Tomas M..:

编辑2018:您最好将BroadcastChannel用于此目的,请参阅下面的其他答案.但是,如果您仍然希望使用localstorage在选项卡之间进行通信,请执行以下操作:

为了在选项卡向其他选项卡发送消息时收到通知,您只需绑定"storage"事件即可.在所有标签中,执行以下操作:

$(window).on('storage', message_receive);

message_receive每次在任何其他选项卡中设置localStorage的任何值时,都会调用该函数.事件监听器还包含新设置到localStorage的数据,因此您甚至不需要解析localStorage对象本身.这非常方便,因为您可以在设置后立即重置值,以有效清理任何痕迹.以下是消息传递的功能:

// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}


// receive message
//
function message_receive(ev)
{
    if (ev.originalEvent.key!='message') return; // ignore other keys
    var message=JSON.parse(ev.originalEvent.newValue);
    if (!message) return; // ignore empty msg or msg reset

    // here you act on messages.
    // you can send objects like { 'command': 'doit', 'data': 'abcd' }
    if (message.command == 'doit') alert(message.data);

    // etc.
}

所以现在,当你的标签绑定onstorage事件,并且你实现了这两个功能时,你可以简单地向其他标签调用消息,例如:

message_broadcast({'command':'reset'})

请记住,两次发送完全相同的消息只会传播一次,因此如果您需要重复消息,请为它们添加一些唯一标识符,例如

message_broadcast({'command':'reset', 'uid': (new Date).getTime()+Math.random()})

还要记住,广播消息的当前选项卡实际上并不接收它,只有同一域上的其他选项卡或窗口.

您可能会问,如果用户在removeItem()之前的setItem()调用之后加载不同的网页或关闭其选项卡会发生什么.好吧,根据我自己的测试,浏览器会暂停卸载,直到整个功能message_broadcast()完成.我测试了将一些非常长的for()循环放入其中并且它仍然等待循环结束然后关闭.如果用户只在中间杀死了标签,那么浏览器将没有足够的时间将消息保存到磁盘,因此这种方法对我来说似乎是安全的方式,如何发送没有任何痕迹的消息.欢迎评论.


Safari不支持BroadcastChannel - https://caniuse.com/#feat=broadcastchannel

2> user..:

有一个专门用于此目的的现代API - 广播频道

它很简单:

var bc = new BroadcastChannel('test_channel');

bc.postMessage('This is a test message.'); /* send */

bc.Onmessage= function (ev) { console.log(ev); } /* receive */

消息不需要只是一个DOMString,可以发送任何类型的对象.

可能除了API清洁之外,它还是此API的主要优点 - 没有对象字符串化.

目前仅支持 Chrome和Firefox,但您可以找到使用localStorage的polyfill.


有一个很好的项目在这里跨浏览器库中包含这个功能:https://github.com/pubkey/broadcast-channel
等等,你怎么知道消息来自哪里?它是否忽略来自同一选项卡的消息?
@zehelvion:发件人不会收到它,例如[好概述](https://developers.google.com/web/updates/2016/09/broadcastchannel).此外,您可以随意输入任何内容,包括.如果需要,发件人的一些ID.

3> Nacho Coloma..:

对于那些寻找不基于jQuery的解决方案的人来说,这是Thomas M提供的解决方案的简单Javascript版本:

window.addEventListener("storage", message_receive);

function message_broadcast(message) {
    localStorage.setItem('message',JSON.stringify(message));
}

function message_receive(ev) {
    if (ev.key == 'message') {
        var message=JSON.parse(ev.newValue);
    }
}


我只关注jQuery和Javascript之间的差异.

4> softvar..:

Checkout AcrossTabs - 跨源浏览器选项卡之间的轻松通信.它结合使用postMessage和sessionStorage API,使通信变得更加容易和可靠.


有不同的方法,每种方法都有自己的优点和缺点.让我们讨论每个:

    localStorage的

    优点:

      可以简单地将Web存储视为对COOKIE的改进,从而提供更大的存储容量.如果您查看Mozilla源代码,我们可以看到5120KB(5MB,相当于Chrome上的250万个字符)是整个域的默认存储大小.与典型的4KB COOKIE相比,这为您提供了更多的工作空间.

      对于每个HTTP请求(HTML,图像,Javascript,CSS等),数据不会发送回服务器 - 减少客户端和服务器之间的流量.

      存储在localStorage中的数据将一直存在,直到被明确删除.所做的更改已保存,可用于当前和将来对网站的所有访问.

    缺点:

      它适用于同源策略.因此,存储的数据只能在同一个来源上使用.

    饼干

    优点:

      与其他人相比,AFAIK没什么.

    缺点:

      4K限制适用于整个COOKIE,包括名称,值,到期日期等.要支持大多数浏览器,请将名称保留在4000字节以下,并将整体COOKIE大小保持在4093字节以下.

      每次HTTP请求(HTML,图像,Javascript,CSS等)都会将数据发送回服务器 - 增加客户端和服务器之间的流量.

      通常,允许以下内容:

      总共300个饼干

      每个COOKIE 4096个字节

      每个域20个COOKIE

      每个域81920字节(给定20个最大大小为4096的COOKIE = 81920字节.)

    的sessionStorage

    优点:

      它类似于localStorage.

      更改仅适用于每个窗口(或Chrome和Firefox等浏览器中的标签).所做的更改将保存并可用于当前页面,以及将来在同一窗口中访问该站点.窗口关闭后,将删除存储

    缺点:

      数据仅在设置它的窗口/选项卡中可用.

      数据不是持久的,即一旦窗口/标签关闭就会丢失.

      比如localStorage,tt适用于同源策略.因此,存储的数据只能在同一个来源上使用.

    PostMessage的

    优点:

      安全地实现跨源通信.

      作为数据点,WebKit实现(由Safari和Chrome使用)目前不会强制执行任何限制(除了内存不足所强加的限制).

    缺点:

      需要从当前窗口打开一个窗口,然后只要你打开窗户就可以进行通信.

      安全问题 - 通过postMessage发送字符串是您将获取由其他Javascript插件发布的其他postMessage事件,因此请务必对targetOrigin传递给消息侦听器的数据执行和完整性检查.

    PostMessage + SessionStorage的组合

    使用postMessage在多个选项卡之间进行通信,同时在所有新打开的选项卡/窗口中使用sessionStorage来持久传递数据.只要选项卡/窗口保持打开状态,数据就会保留.因此,即使开启者选项卡/窗口关闭,打开的选项卡/窗口也会在刷新后获得整个数据.

我为此编写了一个Javascript库,名为AcrossTabs,它使用postMessage API在跨源选项卡/窗口和sessionStorage之间进行通信,以便在它们存在时保持打开的选项卡/窗口标识.



5> datasedai..:

人们应该考虑使用的另一种方法是共享工人.我知道这是一个前沿概念,但你可以在共​​享工作者上创建一个比localstorage快很多的中继,并且不需要父/子窗口之间的关系,只要你在同一个来源.

在这里看到我的答案,我对此做了一些讨论.



6> Alex..:

有一个很小的开源组件可以在相同来源的标签/窗口之间进行同步/通信(免责声明 - 我是其中一个贡献者!)localStorage.

TabUtils.BroadcastMessageToAllTabs("eventName", eventDataString);

TabUtils.OnBroadcastMessage("eventName", function (eventDataString) {
    DoSomething();
});

TabUtils.CallOnce("lockname", function () {
    alert("I run only once across multiple tabs");
});

https://github.com/jitbit/TabUtils

PS我冒昧地推荐它,因为当事件几乎同时发生时,大多数"lock/mutex/sync"组件都在websocket连接上失败


推荐阅读
  • 本文介绍了在满足特定条件时如何在输入字段中使用默认值的方法和相应的代码。当输入字段填充100或更多的金额时,使用50作为默认值;当输入字段填充有-20或更多(负数)时,使用-10作为默认值。文章还提供了相关的JavaScript和Jquery代码,用于动态地根据条件使用默认值。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
  • 第一种<script>$(".eq").on(&qu ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • Ihaveaforminadirectivetemplate:我在指令模板中有一个表单:<formn ... [详细]
  • Java大文件HTTP断点续传到服务器该怎么做?
    最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆 ... [详细]
  • html5 localStorage的读取
    localStorage的读取if(!window.localStorage){alert(浏览器支持localstorage);}else{varstoragewindo ... [详细]
  • IamgettingaUnicodeerror:UnicodeEncodeError:charmapcodeccantencodecharacteru\xa9in ... [详细]
  • 这篇文章主要介绍PHP如何使用在全部作用域中始终可用的内置变量,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要 ... [详细]
author-avatar
mobiledu2502871243
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有