capo_greco
capo_greco7mo ago

Can I add properties to a websocket object?

console.dir (socket.id)
console.dir (socket)

Object.assign (this.control.id, socket.id)
console.dir (socket.id)
console.dir (socket)

Object.assign (this.control.id, socket.id)
I am adding an id object to the sockets to help keep track of them, but something is giving rise to this behaviour, which doesn't seem to make sense
No description
6 Replies
Deno AI Helper
Deno AI Helper7mo ago
I wasn't able to find the answer to your question in the official Deno documentation. However, based on the code snippet you've provided, I can offer some general JavaScript advice. In JavaScript, you can add properties to most objects, including WebSocket objects, as they are just instances of the WebSocket class which is a type of object. However, there are a few things to note in your code: 1. console.dir(socket.id) - This line suggests that you are trying to log the id property of the socket object. If socket.id is not already defined, this will log undefined. 2. Object.assign(this.control.id, socket.id) - This line is attempting to copy the value of socket.id to this.control.id. However, Object.assign is typically used to copy the values of all enumerable own properties from one or more source objects to a target object. If socket.id is a primitive value (like a string or number), you don't need Object.assign. You can simply assign it directly:
this.control.id = socket.id;
this.control.id = socket.id;
If socket.id is an object and you want to merge its properties into this.control.id, then you should ensure that this.control.id is an object before using Object.assign:
this.control.id = this.control.id || {}; // Ensure this.control.id is an object
Object.assign(this.control.id, socket.id);
this.control.id = this.control.id || {}; // Ensure this.control.id is an object
Object.assign(this.control.id, socket.id);
Please note that this advice is not based on the Deno documentation, and you should double-check the accuracy of the advice given. If you continue to experience unexpected behavior, it may be helpful to provide more context or review the surrounding code to ensure that the WebSocket object and the this.control object are being used as intended.
NDH
NDH7mo ago
Each new WebSocket Client sends a unique id in its request header. On the server, I use the client id to identify this connection.
let id = '';
// When ready, sends this client its unique id.
socket.onopen = () => {
id = request.headers.get('sec-websocket-key') || 'id'
if (socket.readyState === OPEN) {
socket.send(JSON.stringify({ topic: "Registered", data: { id: id, name: userName } }))
}
}
let id = '';
// When ready, sends this client its unique id.
socket.onopen = () => {
id = request.headers.get('sec-websocket-key') || 'id'
if (socket.readyState === OPEN) {
socket.send(JSON.stringify({ topic: "Registered", data: { id: id, name: userName } }))
}
}
I like to use that as the client.id
I confirm the registration by returning this id to the client. Let me know if you'd like to see the complete WebSocket-Server code. It handles multiple clients.
capo_greco
capo_greco7mo ago
brilliant - thank you I will bbl to discuss further
NDH
NDH7mo ago
I built a gist for you. https://gist.github.com/nhrones/d37855a844e114b801fac545ef1c5c89#file-ws_clients-md I could build you a very simple chat-app in a public repo if that would help you.
Very simple is best if you just want to see the communications work. Also Note: This key is NOT UUID, but will be unique enough for most WS apps.
The sec_websocket_key is calculated by base64 encoding a random string of 16 characters each with an ASCII value between 32 and 127.
A different key will be randomly generated for each new connection.
~39 Trillion IDs needed, in order to have a 1% probability of at least one collision. At 10 IDs per second, would take ~126,000 years to create one collision!
~39 Trillion IDs needed, in order to have a 1% probability of at least one collision. At 10 IDs per second, would take ~126,000 years to create one collision!
Because we use a Map, We could simple detect an ID collision, and just handle it
if (map.has(id)) handleNotUnique();
if (map.has(id)) handleNotUnique();
capo_greco
capo_greco7mo ago
hi! @Altair 680b ok I am back at my computer I am trying to coordinate across servers with BroadcastChannel, as well as across instances with WebSockets I am also generating memorable names for each server and client instance I am using Maps to keep track of everything is it possible to attach the memorable names etc. directly onto the weboscket objects themselves, or would I need to create an encapsulating object
NDH
NDH7mo ago
As I demonstrated in the gist, I would just wrap the socket like below(client), The socket instance then remains optimal and its use is independent of the tracking object. Adding a property to an instance object may impact its overall performance. I would then use either your id or name as the key for the clients map.
/** Websocket client collection */
const clients: Map<string, Client> = new Map()

/** Registers a new WebSocket client
* handles all socket events and messaging
* @param { WebSocket } socket - WebSocket connection
* @param { string | null } id - request.headers.get('sec-websocket-key')
*/
export const connectClient = (socket: WebSocket, id: string) => {
const thisClient = id; // sec-websocket-key

// create the new client object
const client: Client = {
id: thisClient,
name: "",
socket: socket,
};

// register this new client in your collection
clients.set(id, client);
/** Websocket client collection */
const clients: Map<string, Client> = new Map()

/** Registers a new WebSocket client
* handles all socket events and messaging
* @param { WebSocket } socket - WebSocket connection
* @param { string | null } id - request.headers.get('sec-websocket-key')
*/
export const connectClient = (socket: WebSocket, id: string) => {
const thisClient = id; // sec-websocket-key

// create the new client object
const client: Client = {
id: thisClient,
name: "",
socket: socket,
};

// register this new client in your collection
clients.set(id, client);
I'd prefer using the id as it will be unique.