1

So I'm trying to have a real-time display of my online players, and it's working great thus far except for one issue. When my app listens for the disconnect, it appears that a page refresh triggers this function and said player is logged out.

app.io.route("disconnect", function(req,res) {
    db.query("UPDATE player_data SET online=0 WHERE id="+mysql.escape(req.session.user));
    req.io.broadcast("event", {msg:req.session.username+" has logged out!"});
    app.io.broadcast("reloadXY");
    req.session.destroy();
});

Why is a page refresh triggering this function? (I know it's this function because the only other way a player is logged out is via the logout link) How can I have it ignore page refreshes and only catch disconnections like closing the browser?

Edit: how can I "ping" for the reconnect event so that I can check if the page was reloaded versus closed? A reload will have an instant re-connection, so I just need to check for said reconnection. I just don't know how!

Sterling Archer
  • 22,070
  • 18
  • 81
  • 118
  • As far as web sockets are concerned, refreshing the page is just like closing the browser. You may have to rethink your strategy for detecting a user disconnection. For example: rather than using only the disconnect event, have a timeout value as well. If the user does not reconnect to your server in X seconds after a disconnection, that is when you broadcast the disconnect message. –  May 16 '14 at 17:59
  • @TimCooper I was just reading up on something like that, but I'm having trouble creating a test case. Do you have express.io documentation on reconnecting tests? – Sterling Archer May 16 '14 at 18:04

1 Answers1

2

Thanks to Zirak (and Tim Cooper, although at the time I had no idea what he meant), I was able to solve this issue. He suggested I store a disconnection timeout inside my session, and when there is a re-connection (instant because of page-reloads), simply clear the timeout before it auto-logs out the player.

app.io.route("stopDisconnection", function(req) {
    if (req.session) {
        clearTimeout(req.session.disconnection);
        console.log("Timeout cleared");
    }
});

app.io.route("disconnect", function(req) {
    req.session.disconnection = setTimeout(function() {
        console.log("User timed out!");
        db.query("UPDATE player_data SET online=0 WHERE id="+mysql.escape(req.session.user));
        app.io.broadcast("event", {msg:req.session.username+" has logged out!"});
        app.io.broadcast("reloadXY");
        req.session.destroy();
    },5000);
});

And simply call io.emit("stopDisconnection") on index.html

And with that, you can successfully trigger a disconnect function without having to worry about a page refresh also trigger the event.

Sterling Archer
  • 22,070
  • 18
  • 81
  • 118
  • 1
    Conclusion: Dynamic languages are the best. You could never do something like this on (just picking some random language here...) Java. – Zirak May 16 '14 at 23:49
  • Isn't 5 seconds quite short? The time for the user to reload the page, reconnect to the socket, and for the "stopDisconnection" message to go back to the server might be short on local dev, but not enough for slow users. – Florian Margaine May 16 '14 at 23:55
  • @FlorianMargaine yeah I'm worried about that. Might extend it if/when problems arise – Sterling Archer May 17 '14 at 01:40