如何在 sharedworkers 中使用 html5 websockets
Posted
技术标签:
【中文标题】如何在 sharedworkers 中使用 html5 websockets【英文标题】:How to use html5 websockets within sharedworkers 【发布时间】:2021-06-22 09:43:30 【问题描述】:在查看 *** 上的类似问题后,我没有发现任何对我想要在我的项目中做的事情有多大帮助。阅读和研究我成功地使应用程序与我的 Ratchet php websocket 服务器建立了多个连接,但我注意到每次用户重新加载页面或在新选项卡中打开链接时,客户端 websocket 都会断开连接,然后再次重新连接。
所以,我想知道如何在使用 Sharedworker 的 Web 应用程序中为多个用户只获得一个到 WebSocket 服务器的持久连接。
我在客户端是这样的:
<script>
$(document).ready(function($)
let socket = new WebSocket("ws://realtime:8090");
socket.onopen = function(e)
console.log("Browser client connected to websocket server");
socket.send("Greetings from the browser!");
;
socket.onmessage = function(event)
console.log('Data received from server: ' + event.data);
;
socket.onclose = function(event)
if (event.wasClean)
console.log(`Connection closed cleanly, code=$event.code reason=$event.reason`);
else
// e.g. server process killed or network down
// event.code is usually 1006 in this case
console.log('Connection closed unexpectedly.');
;
socket.onerror = function(error)
alert(error.message);
;
);
</script>
【问题讨论】:
【参考方案1】:好的,在阅读、研究和尝试不同的东西和代码示例之后,我得出了这个解决方案:
客户端(浏览器)应该与 Sharedworker 建立连接。 sharedworker 是一个单独的 javascript 文件,其中包含 sharedworker 的核心以及需要在其中执行的任何其他 JS 代码。 我首先测试了 sharedworker 在浏览器选项卡上的正常工作,计算每个用户打开的选项卡的数量,并将消息共享给一个用户,然后共享给一组用户。 一旦浏览器和 Sharedworker 之间的通信通过了这些测试,我就将 websocket 代码添加到 Sharedworker JS 文件的正文中。
最后,客户端(浏览器)是这样的:
<script>
$(document).ready(function($)
var currentUser = " Auth::user()->name ";
let worker = new SharedWorker('worker.js');
worker.port.start();
worker.port.postMessage(
action: 'connect',
username: currentUser
);
worker.port.onmessage = function(message)
console.log(message.data);
;
);
</script>
Sharedworker 如下所示:
// All this code is executed only once, until the onconnect() function.
//---------------------------------------------------------------------
// The array AllPorts contains objects with the format user:<string>, port:<MessagePort>
let AllPorts = [];
var socket = new WebSocket("ws://ssa:8090");
// Called when the WebSocket Server accepts the connection.
socket.onopen = function(e)
//
;
// Event handler fired when the WebSocket Server sends a message to this client.
socket.onmessage = function(e)
var message = JSON.parse(e.data);
// This loop sends a message to each tab opened by the given user.
for (var i = 0; i < AllPorts.length; i++)
if (AllPorts[i].user == message.to)
AllPorts[i].port.postMessage(message.msg);
;
socket.onclose = function(event)
if (event.wasClean)
console.log('Connection closed normally');
else
console.log('Connection closed unexpectedly.');
;
socket.onerror = function(error)
console.log(error.message);
;
// This event handler is fired every time a new tab is opened on the web browser.
onconnect = function(ev)
let port = ev.ports[0];
port.onmessage = function(e)
console.log(e.data.action);
let currentUser = e.data.username;
let userIsConnected = false;
switch (e.data.action)
case "connect":
for (var i = 0; i < AllPorts.length; i++)
if (AllPorts[i].user == currentUser)
userIsConnected = true;
// Add new connected tab to AllPorts array.
AllPorts.push(user: currentUser, port: port);
if (!userIsConnected)
// New users are added to the list of the WebSocket Server.
setTimeout(() =>
socket.send(JSON.stringify(action: 'connect', username: currentUser));
, 600);
break;
case "close":
console.log(AllPorts);
var index;
// This is also executed when the user reloads the Tab.
for (var i = 0; i < AllPorts.length; i++)
if (AllPorts[i].port == port)
index = i;
currentUser = AllPorts[i].user;
AllPorts.splice(index, 1);
userIsConnected = false;
// Check for any connected tab.
for (var i = 0; i < AllPorts.length; i++)
if (AllPorts[i].user == currentUser)
userIsConnected = true;
if (!userIsConnected)
// User doen't have more tabs opened. Remove user from WebSocket Server.
socket.send(JSON.stringify(action: 'disconnect', username: currentUser));
break;
case "notify":
// Check if given user is connected.
for (var i = 0; i < AllPorts.length; i++)
if (AllPorts[i].user == currentUser)
userIsConnected = true;
if (userIsConnected)
socket.send(JSON.stringify(action: 'notify', to: currentUser, message: e.data.message));
// switch
// port.onmessage
// onconnect
【讨论】:
以上是关于如何在 sharedworkers 中使用 html5 websockets的主要内容,如果未能解决你的问题,请参考以下文章
Deno Web Worker API - SharedWorker