如何在 sharedworkers 中使用 html5 websockets
How to use html5 websockets within sharedworkers
在查看关于 Whosebug 的类似问题后,我没有发现任何对我想在我的项目中做的事情有帮助的东西。阅读和研究我成功地使应用程序与我的 Ratchet PHP websocket 服务器建立了多个连接,但我注意到每次用户重新加载页面或在新选项卡中打开 link 时,客户端 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>
好的,在阅读、研究和尝试不同的东西和代码示例之后,我得出了这个解决方案:
客户端(浏览器)应该连接到 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
在查看关于 Whosebug 的类似问题后,我没有发现任何对我想在我的项目中做的事情有帮助的东西。阅读和研究我成功地使应用程序与我的 Ratchet PHP websocket 服务器建立了多个连接,但我注意到每次用户重新加载页面或在新选项卡中打开 link 时,客户端 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>
好的,在阅读、研究和尝试不同的东西和代码示例之后,我得出了这个解决方案:
客户端(浏览器)应该连接到 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