Reputation: 2520
I'm making an application for our website where users can send chat messages with each other. I've managed to do this successfully using nodejs and socketio. I have a header with some sort of notification icon just like facebook that can be seen in all the pages. Now if the user opens multiple tabs and he receives a message, then all open tabs should see the icon light up. I've gotten this to work by tracking the socket connections opened by users through a 2D array of sockets:
var container = {};
io.sockets.on( 'connection', function(client) {
client.on('set account online', function(username) {
if (!(username in container)) {
console.log(username + " is now Online" );
container[username] = [];
}
client.username = username;
container[username].push(client);
});
client.on('set account offline', function(username) {
if (username in container) {
delete container[username];
console.log(username + " is now Offline" );
}
});
And then when a message is sent I iterate through the appropriate array element
client.on('send message', function(data) {
if (data.recipient in container) {
var clients = container[data.recipient];
for(var i = 0; i < clients.length;i++){
clients[i].emit('send message', {recipient: data.recipient, message: data.message });
}
}
});
That's working well and all (not sure how well coded it is though). The problem is if the user closes a tab, the socket for that tab still exists in the container
variable and node would still try to emit to that socket if a message is received for that particular user. Also it just feels cleaner to un-track any disconnected socket.
I've been thinking about this and I think I have to tie the socket disconnect event to the client side's onbeforeunload
event and we all know how that performs across different browsers. Any suggestion regarding what's the proper way to splice off disconnected sockets from the container
array?
Upvotes: 0
Views: 2934
Reputation: 32127
As per my comment:
You should really be implementing rooms. On each connection each user should join their own room, any additional connections from the same user should join this room. You can then emit data to the room and each client inside it will receive the data.
Your code can be changed to:
io.sockets.on('connection', function(client) {
client.on('set account online', function(username) {
client.join(username);
});
client.on('set account offline', function(username) {
client.leave(username);
});
client.on('send message', function(data) {
io.to(data.recipient).emit('send message', {
recipient: data.recipient,
message: data.message
});
});
});
Upvotes: 3