Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 同一域上不同窗口之间的通信_Javascript_Postmessage - Fatal编程技术网

Javascript 同一域上不同窗口之间的通信

Javascript 同一域上不同窗口之间的通信,javascript,postmessage,Javascript,Postmessage,我正在构建一个应用程序,它执行大量客户端数据下载和处理。数据处理通过在位于子域上的iframe中进行处理而与主应用程序隔离。正是这个iframe下载了数据。通信是通过邮递信息进行的 一切都很好,只是可能会更好 如果用户打开额外的选项卡/窗口,应用程序当前会重新加载所有数据,甚至可能重复处理工作,这不是问题,只是它会降低速度,页面加载时间更长 我想做的是让每个顶级选项卡/窗口只与一个正在处理的iframe通信,如果原始窗口关闭,可以恢复iframe。问题是,它们不是通过javascript打开的,

我正在构建一个应用程序,它执行大量客户端数据下载和处理。数据处理通过在位于子域上的iframe中进行处理而与主应用程序隔离。正是这个iframe下载了数据。通信是通过邮递信息进行的

一切都很好,只是可能会更好

如果用户打开额外的选项卡/窗口,应用程序当前会重新加载所有数据,甚至可能重复处理工作,这不是问题,只是它会降低速度,页面加载时间更长

我想做的是让每个顶级选项卡/窗口只与一个正在处理的iframe通信,如果原始窗口关闭,可以恢复iframe。问题是,它们不是通过javascript打开的,而是通过普通的浏览器方法打开选项卡中的链接,因此我无法获得发送消息所需的iframe引用

我是否可以将iframe的窗口引用传递给其他选项卡,以便它们可以通过postMessage与之通信?这是否可以通过共享工作人员以某种方式实现

我意识到我可以在整个处理任务中使用共享的worker,但这也有它自己的问题,因为数据来自第三方域,无法从worker内部访问

只需要与所有主要浏览器的最新版本兼容

编辑:我刚刚发现SharedWorker还没有在firefox中实现,所以我想这是行不通的。我还有别的方法可以做到这一点吗

编辑2:我发现您可以使用:

var win = window.open('', 'my_window_name'); 

从任何其他窗口捕获对iframe的引用。但是,如果iframe不存在,它将作为窗口打开它。即使它立即关闭,也会导致闪烁,并导致“弹出阻止”消息,使其无法使用。

如果其他人发现了这一点,我会想出一个解决方案。它有点粗糙,需要进一步测试。但到目前为止,它正在发挥作用。如果需要,它可以跨域工作

它使用两种技巧的组合

首先是使用

remote_window = window.open("", "remote_window_name");
获取对窗口的引用。这是因为如果一个窗口已经以给定的名称打开,那么将返回对该窗口的引用,而不是打开一个新窗口

但是,它确实存在一个问题,即如果iframe不存在,则会弹出一个新窗口。为了防止这种情况,使用了本地存储。加载窗口/选项卡时,它会检查本地存储,以查看是否有另一个页面已经具有共享iframe。如果没有,它将插入iframe,并在本地存储器中设置一个标志,表示它可用

最后,如果窗口仍然打开,则使用try块关闭新打开的窗口。try块可防止跨域错误。这意味着最糟糕的情况是用户看到一个弹出窗口并消失,或者他们会看到“启用弹出窗口”消息。我还没有设法在测试中触发这种情况——这只是一个边缘案例

try {
    if(store_window.location.href === "about:blank" ){
        remote_window.close();
        remote_window = insertIfame();
    }
} catch(err) {
}
添加了一个onunload事件,该事件将在页面关闭时删除该标志

此外,还会创建一个setInterval,用于不断刷新超时标志。我让它每秒运行4次;当加载第二个窗口/选项卡时,它会检查iframe标志是否在尝试与其通信之前未超时。这是一个很小的开销,但远低于我加载第二个iframe的成本。如果浏览器崩溃或onunload因任何原因未启动,这可用于防止过时数据。我在检查超时(目前为1秒)时有一个小的回旋余地,以防主窗口陷入循环。回旋余地仅在超时上,而不是完全删除标志的卸载事件

如果带有iframe的原始窗口已关闭,则每次发送消息时都需要检查该标志。发生这种情况时,iframe将重新插入第一个需要它的打开窗口中,并重置标志

发回信息很容易。只需使用receiveMessage的event.source属性-它指向发送窗口


最后一个需要说明的边缘情况是,如果主窗口关闭,而它的iframe是辅助窗口的中间进程。理论上,这可以通过在iframe中使用onunload事件将消息发送回任何处理数据的窗口来解决。但是我还没有实现它,在页面卸载之前它可能还没有完成。另一种处理方法是在检查标志和重试的辅助窗口中设置一个超时,我可能会这样做,因为消息已经附加了超时。

我认为web workers不是一个选项,因为它只能在IE 10中工作;-)使用html5本地存储,可能是?@pahnin这是个好主意。我将做一个实验。@pahnin我看不到一种方法可以将窗口引用转换为字符串,然后再转换回来。如果使用SharedWorkers,这也会是一个问题。@SystemicPlural简单地将长期运行的过程的结果和/或进度存储在
localStorage
(我认为pahnin可能也是这个意思)。然后,您可以定期检查其状态,并在完成后显示结果。窗口到字符串对窗口内容的引用听起来很脆弱和棘手。