标签或窗口之间的通信 [英] Communication between tabs or windows

查看:142
本文介绍了标签或窗口之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方式如何多个标签或窗口之间在浏览器中不留痕迹沟通(在同一个域,而不是CORS)。有几种解决方案:

I was searching for a way how to communicate between multiple tabs or windows in a browser (on the same domain, not CORS) without leaving traces. There were several solutions:


  1. using窗口对象

  2. postMessage

  3. cookies

  4. localStorage

  1. using window object
  2. postMessage
  3. cookies
  4. localStorage

首先是可能是最糟糕的解决方案 - 你需要从你的当前窗口中打开一个窗口,然后你可以为您保留的窗户只开只要沟通。如果你重新载入页面中的任何窗口,你最有可能失去通信。

The first is probably the worst solution - you need to open a window from your current window and then you can communicate only as long as you keep the windows open. If you reload the page in any of the windows, you most likely lost the communication.

第二方法,使用postMessage的,可能使跨源的通信,但是遭受同样的问题,因为第一种方法。你需要保持一个窗口对象。

Second approach, using postMessage, probably enables cross-origin communication, but suffers the same problem as the first approach. You need to maintain a window object.

第三条道路,使用cookie,存储在浏览器中的一些数据,可有效看起来像在同一个域将消息发送到所有窗口,但问题是,你永远无法知道,如果所有选项卡读取消息已经或没有清理了。你必须实现某种超时定期读取cookie。此外,您是通过cookie的最大长度,这是4KB限制。

Third way, using cookies, store some data in the browser, which can effectively look like sending a message to all windows on the same domain, but the problem is that you can never know if all tabs read the "message" already or not before cleaning up. You have to implement some sort of timeout to read the cookie periodically. Furthermore you are limited by maximum cookie length, which is 4KB.

第四溶液,使用本地存储,似乎克服饼干的限制,并且它甚至可以听到使用事件。怎么样?让我回答我的问题解释一下。

Fourth solution, using localStorage, seemed to overcome the limitations of cookies, and it can be even listen-to using events. How? Let me explain by answering my own question.

推荐答案

为了当标签发送消息给其他选项卡得到通知,你只需要在存储事件绑定。在所有选项卡,做到这一点:

In order to get notified when a tab sends a message to other tabs, you simply need to bind on 'storage' event. In all tabs, do this:

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

功能 message_receive 将被调用每次你设置的localStorage的任何值在任何其他选项卡中的时间。事件监听器还包含新设置为localStorage的数据,所以你甚至不需要解析localStorage的对象本身。这是非常方便的,因为你可以重置价值它仅有之后,有效地清理任何痕迹。这里有函数消息:

The function message_receive will be called every time you set any value of localStorage in any other tab. The event listener contains also the data newly set to localStorage, so you don't even need to parse localStorage object itself. This is very handy because you can reset the value just right after it was set, to effectively clean up any traces. Here are functions for messaging:

// 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事​​件,你有这两个功能实现的,你可以简单的广播消息,以其他标签调用,例如:

So now once your tabs bind on the onstorage event, and you have these two functions implemented, you can simply broadcast a message to other tabs calling, for example:

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

请注意,发送完全相同的消息两次将只繁殖一次,所以如果你需要重复的邮件,添加一些独特的标识符给他们,像

Remember that sending the exact same message twice will be propagated only once, so if you need to repeat messages, add some unique identifier to them, like

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

还记得哪些广播消息当前标签实际上并没有得到它,只有其他标签或窗口在同一个域。

Also remember that the current tab which broadcasts the message doesn't actually receive it, only other tabs or windows on the same domain.

您可能会问,如果用户加载不同的网页或只是setItem调用(后关闭他的标签会发生什么)在之前的removeItem()。那么,从我自己的测试浏览器整合卸载搁置,直到 message_broadcast()完成整个功能。我测试把inthere一些很长的()循环,它仍然等待着周期截止前完成。如果用户杀死标签只是其间,那么浏览器就会没有足够的时间来保存邮件到磁盘上,因此,这种方法似乎对我来说,安全的方式如何,没有任何痕迹发送消息。欢迎评论。

You may ask what happens if the user loads a different webpage or closes his tab just after the setItem call() before the removeItem(). Well, from my own testing the browser puts unloading on hold until the entire function message_broadcast() is finished. I tested to put inthere some very long for() cycle and it still waited for the cycle to finish before closing. If the user kills the tab just inbetween, then the browser won't have enough time to save the message to disk, thus this approach seems to me like safe way how to send messages without any traces. Comments welcome.

这篇关于标签或窗口之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆