I’m writing a multi-room chat app with Node.js and Socket.IO and I’m wondering how to handle data that needs to persist for the duration of a session, when the transport is xhr-polling.
Currently, on the client I’m sending a “join” event on connection, which passes a long a few variables (such as username), which I store server-side using Socket.IO’s get and set methods. They are then available until the client disconnects.
This works fine if the transport is Websockets, but if it falls back to xhr-polling, the join event is emitted on each connect, which happens every 5-10 seconds. (Similarly, “such and such has left/joined the room” is sent on each xhr-poll request, which is also undesirable.)
I’m not sure what the best way forward is. I can’t disable xhr-polling as it’s a needed fallback for flashless IE for one.
Here is the relevant client code:
socket.on("connect", function(){
socket.emit("join", { username: username, room: room });
});
And on the server:
var io = require("socket.io").listen(8124)
, buffer = {}
, max_room_buffer = 15;
io.sockets.on("connection", function(socket) {
socket.on("join", function(data){
if(data.username && data.room) {
socket.set("data", data);
socket.join(data.room);
if(!buffer[data.room]) buffer[data.room] = [];
socket.broadcast.to(data.room).emit("message", "<em>" + data.username + " has joined room " + data.room + "</em>");
socket.emit("message", "<em>You have joined room " + data.room + "</em>");
socket.emit("message", buffer[data.room]);
}
});
socket.on("message", function(message) {
if(message) {
socket.get("data", function(err, data){
if(data) {
var msg = "<span>" + data.username + ":</span> " + message;
buffer[data.room].push(msg);
if(buffer[data.room].length > max_room_buffer) buffer[data.room].shift();
io.sockets.in(data.room).emit("message", msg);
}
});
}
});
socket.on("disconnect", function () {
socket.get("data", function(err, data){
if(data) {
socket.leave(data.room);
socket.broadcast.to(data.room).emit("message", "<em>" + data.username + " has left room " + data.room + "</em>");
}
});
});
});
Thanks in advance.
Perhaps I’m missing something, but wouldn’t this work.
Client:
Server:
As for the fact that the connection event occurs on every new poll, that’s an unavoidable consequence of XHR polling. Since each poll is a new HTTP request, there is no state from the previous request, so you need to set it up again.
If you want to reduce how frequently this happens, you could try increasing the polling duration from its default of 20. For example: