javascript 跨浏览器选项卡共享 websocket?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9554896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 07:02:25  来源:igfitidea点击:

Sharing websocket across browser tabs?

javascripthtmlnode.jswebsocketweb-worker

提问by singhsumit

We want to have one socket per browser rather than one per tab in a browser. How can we achieve it? I read about shared web workers which was promising. A reference for that too is appreciated. Unfortunately shared web workers are not yet implemented by mozilla or internet explorer to the best of my knowledge. So what to do in this case ? We are working on node.js on server side.

我们希望每个浏览器都有一个套接字,而不是浏览器中的每个选项卡。我们怎样才能实现它?我读到了很有前途的共享网络工作者。对此的参考也表示赞赏。不幸的是,就我所知,mozilla 或 Internet Explorer 尚未实现共享的 Web Worker。那么在这种情况下该怎么办?我们正在服务器端开发 node.js。

回答by Donghwan Kim

After seeing this question, I've finally implemented sharing socket and added to my library a few days ago. It seems to work in most of browsers including even in IE6, but except Opera. For Opera, you may use regular checking instead of unload event.

看到这个问题后,我终于在几天前实现了共享套接字并添加到我的库中。它似乎适用于大多数浏览器,甚至包括 IE6,但 Opera 除外。对于 Opera,您可以使用定期检查而不是卸载事件。

Check releated issue at https://github.com/flowersinthesand/portal/issues/21

https://github.com/flowersinthesand/portal/issues/21检查相关问题

Leaving a cookie

留下饼干

  1. Set cookie to inform there is a shared socket.
  2. When socket closes, remove that cookie to inform there is no shared socket.
  1. 设置 cookie 以通知存在共享套接字。
  2. 当套接字关闭时,删除该 cookie 以通知没有共享套接字。

See, https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L629-650

见,https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L629-650

Sharing and using shared socket

共享和使用共享套接字

  1. Using the storage event and localStorage - The localStorage fires the storage event when a value is set and removed.
    1. Check that StorageEvent and localStorage are supported.
    2. Add storage event handler which filters event by key. I used socket's url as key
    3. Add close event of socket which removes storage attributes
    4. To signal, set data with the previous key to storage
  1. 使用存储事件和 localStorage - localStorage 在设置和删除值时触发存储事件。
    1. 检查是否支持 StorageEvent 和 localStorage。
    2. 添加按键过滤事件的存储事件处理程序。我使用套接字的 url 作为键
    3. 添加删除存储属性的套接字关闭事件
    4. 要发出信号,请使用先前的键将数据设置为存储

Sharing: https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L531-568

分享:https: //github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L531-568

Using shared: https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L851-893

使用共享:https: //github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L851-893

  1. Using the window.open method - If we know a shared window's name, we can get that window's reference and access its property.
    1. Every browser supports the window.open method, but some browsers like Chrome prohibit to access the returned window's properties.
    2. Get or create iframe whose name attribute is key. I used socket's url, but note that IE doesn't allow to use non-word characters in name attribute of iframe tag.
    3. Iframe's contentWindow is a shared window reference. Set callbacks variable to store each window's listener.
    4. To signal, simply call callbacks with data. Note that IE 8 and less allow to pass only string to other window's function, and the shared window could be destoryed.
  1. 使用 window.open 方法 - 如果我们知道共享窗口的名称,我们可以获取该窗口的引用并访问其属性。
    1. 每个浏览器都支持 window.open 方法,但某些浏览器(如 Chrome)禁止访问返回的窗口属性。
    2. 获取或创建名称属性为键的 iframe。我使用了套接字的 url,但请注意 IE 不允许在 iframe 标签的 name 属性中使用非单词字符。
    3. iframe 的 contentWindow 是一个共享窗口引用。设置回调变量以存储每个窗口的侦听器。
    4. 要发出信号,只需使用数据调用回调即可。请注意,IE 8 及更低版本只允许将字符串传递给其他窗口的函数,并且共享窗口可能会被销毁。

Sharing: https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L571-605

分享:https: //github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L571-605

Using shared: https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L894-929

使用共享:https: //github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L894-929

Note

笔记

  1. In the above implementation, signalling is broadcasting, so the data should indicate the target. I used target property, p for parent and c for child.
  2. I used additional variables to share socket: opened - whether the shared socket is open, children - list of sharer. Codes and comments will help you understand details.
  1. 在上面的实现中,信令是广播,所以数据应该指示目标。我使用了目标属性,p 为父级,c 为子级。
  2. 我使用额外的变量来共享套接字:opened - 共享套接字是否打开,children - 共享者列表。代码和注释将帮助您了解详细信息。

I hope my answer was helpful.

我希望我的回答有帮助。

回答by Alex

I used the localStorage object for communication between tabs in some occasions. The localStorage object has an event system to tell another tab or window of the same origin that some data has changed ( http://www.codediesel.com/javascript/sharing-messages-and-data-across-windows-using-localstorage/). The idea is, to let the tab with the socket write a timestamp and the received data into the localstorage. If the timestamp gets too old - maybe because the tab with the socket has been closed - another tab can start a socket-connection and update the data and timestamp.

在某些情况下,我使用 localStorage 对象在选项卡之间进行通信。localStorage 对象有一个事件系统来告诉另一个相同来源的选项卡或窗口某些数据已更改(http://www.codediesel.com/javascript/sharing-messages-and-data-across-windows-using-localstorage /)。这个想法是,让带有套接字的选项卡将时间戳和接收到的数据写入本地存储。如果时间戳变得太旧 - 可能是因为带有套接字的选项卡已关闭 - 另一个选项卡可以启动套接字连接并更新数据和时间戳。

回答by Kaustubh Karkare

I am using localStorage as a shared communication channel in order to send data between tabs using an interface identical to EventEmitters. Coupled with a leader election algorithm that decides which tab will be the one connected to the server, I relay all socket events to the leader tab from all follower tabs and vice versa. And finally, the leader tab forwards all events to the server, and broadcasts all received events to all other clients. Here's the code:

我使用 localStorage 作为共享通信通道,以便使用与 EventEmitters 相同的接口在选项卡之间发送数据。结合领导者选举算法,决定哪个选项卡将连接到服务器,我将所有套接字事件从所有跟随者选项卡中继到领导者选项卡,反之亦然。最后,leader 选项卡将所有事件转发到服务器,并将所有接收到的事件广播给所有其他客户端。这是代码:

回答by vanthome

回答by Tom

Far from ideal, but you can use a flash local connection to setup one websocket connection and then share it across tabs and multiple browsers.

远非理想,但您可以使用闪存本地连接来设置一个 websocket 连接,然后跨选项卡和多个浏览器共享它。

See http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/LocalConnection.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6for more information.

有关详细信息,请参阅http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/LocalConnection.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6

回答by Ryan Mann

I'm still theorizing on this for a design I'm getting ready to start building. But, I'm thinking of combining

我仍在为我准备开始构建的设计进行理论分析。但是,我想结合

-WebSockets -Local Storage and -Cross Window Messaging

-WebSockets -本地存储和 -跨窗口消息传递

My theory is to create a socket engine in javascript that runs on every page load in every tab, but will shut down if one already has an established connection.

我的理论是在 JavaScript 中创建一个套接字引擎,该引擎在每个选项卡中的每个页面加载时运行,但如果已经建立了连接,则会关闭。

On first hit to the site, I'll have it make a GUID and store it in local storage, this guid will uniquely identify that users browser/login to their PC.

在第一次访问该站点时,我会为其创建一个 GUID 并将其存储在本地存储中,该 guid 将唯一标识用户浏览器/登录到他们的 PC。

When the socket server accepts a connection it will have that guid, and any new request by that guid will return "999 Connection Already Established" or something like that.

当套接字服务器接受连接时,它将具有该 guid,并且该 guid 的任何新请求都将返回“999 连接已经建立”或类似的信息。

Once one is running, It will seed the other tabs with cross window messaging by converting the data I want to share accross tabs to a JSON blob and then converting that back to an object when received in other tabs. So whichever tab get's the connection, will be handling all incoming/outgoing messages with the socket server. Then it will receive/transmit with the other tabs over cross window messaging. And in theory this should work with Iframe's and Popup windows as well.

一旦运行,它将通过将我想要共享的跨选项卡数据转换为 JSON blob,然后在其他选项卡中收到时将其转换回对象来为其他选项卡提供跨窗口消息传递。因此,无论哪个选项卡获得连接,都将使用套接字服务器处理所有传入/传出消息。然后它将通过跨窗口消息传递与其他选项卡一起接收/传输。从理论上讲,这也适用于 Iframe 和弹出窗口。

This whole system will drive automatic data refreshes on loaded forms for a CRM like system we are building and a live chat system and ticket board.

整个系统将为我们正在构建的类似 CRM 的系统以及实时聊天系统和票务板驱动加载表单上的自动数据刷新。

My dream scenario, is if User A is staring at Ticket 1000 and User B updates ticket 1000 I want user A's ticket to refresh, and if user A made changes before it refreshed I want to give them a data migration pop up to prevent blowing away User B's changed

我梦想的场景是,如果用户 A 盯着票 1000 并且用户 B 更新票 1000 我希望用户 A 的票刷新,如果用户 A 在刷新之前进行了更改,我想给他们一个数据迁移弹出窗口以防止被吹走用户 B 已更改

--User B Made a Conflicting Change while you are editing this record "UserB: FirstName -> Bob" [Take] "UserA: FirstName -> Robert" [Keep]

-- 在您编辑此记录时,用户 B 进行了冲突更改“用户 B:名字 -> 鲍勃”[Take]“用户 A:名字 -> 罗伯特”[保留]

回答by Vitaly

See https://github.com/nodeca/tabex

https://github.com/nodeca/tabex

You need additional layer for cross-tab communication. Tabex has example for Faye use. Other websocket transports (socket.io and so on) can be used in similar way.

您需要额外的层来进行交叉表通信。Tabex 有 Faye 使用的例子。其他 websocket 传输(socket.io 等)可以以类似的方式使用。

回答by almypal

Don't think there seems to be a solution the way socket.io is implemented now. Check out Guillermo Rauch in thisvideo, fifth segment. He too considers it a challenge.

不要认为现在 socket.io 的实现方式似乎有解决方案。在视频中查看 Guillermo Rauch ,第五部分。他也认为这是一个挑战。

回答by Chopping

Actually,It's hard to avoid some of these problems, eg: Disconnect while the network is not stable.After all, pages are aim to exchange different text documents(such as the RFC documents) initially, which just needs a short ,low-cost and unstable transfer approach(the initial purpose of setting up HTTPprotocol as I think)

其实,有些问题是很难避免的,例如:网络不稳定时断开连接。毕竟页面最初是为了交换不同的文本文档(如RFC文档),只需要一个简短的、低成本的和不稳定的传输方法(HTTP我认为设置协议的最初目的)

Of course, to solve it, I suggest u to use the shared worker like the saying above or store the information of the shared and public part with the LocalStorage

当然,为了解决这个问题,我建议你像上面说的那样使用共享的worker或者将共享和公共部分的信息存储在 LocalStorage

Here is the link to the basic usage introduction of LocalStorage

这里是基本用法介绍的链接 LocalStorage

hope it can really hope u!(Actually not yet)

希望它真的可以希望你!(实际上还没有)