1

I'm using a websocket (socket from dart:html) and I wanted to know if I could send a message when the user closes the browser or exits the page.

I tried the onClose event like this:

ws = new WebSocket('ws://$hostname:$port/ws');

ws.onOpen.listen(onSocketOpen);

ws.onClose.listen((e) {
  ws.send("I disconnected");
});

but it won't send anything in these particular cases. Alternatively, on my server I tried this as well, but with the onDone event :

WebSocketTransformer.upgrade(req)
  ..then((socket) => socket.listen((msg) => doSomething(), onDone:() => print("connection closed)));

That works, but I'd like to know what client disconnected (the reason why I wanted to send something from the actual disconnecting client).

Is there a reason to do that? I really don't feel like querying all other clients to know if they're still connected when someone disconnects...

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Pacane
  • 20,273
  • 18
  • 60
  • 97

2 Answers2

4

On the server side, I like to use a data structure that associates a particular connection with a user, then I don't need the client to identify itself as it closes, because I can figure out which client it was using the connection that triggered the onDone(). The simplest way might be to use a Map like this:

Map<String, WebSocket>

In that case, the String is the client ID (or whatever). It's even possible to do it the other way around:

Map<WebSocket, String>

Your onDone() handler will have a WebSocket passed to it, and you can just look that up in your data structure to find out which client is associated with it.

Note that for this to work, your clients need to send identifying information as the first order of business once they're connected. When they do, you just create the association in your Map.

Clear as mud?

montyr75
  • 881
  • 1
  • 5
  • 8
  • 1
    That's the usual way you would do it. +1 – Robert Nov 22 '14 at 08:53
  • @montyr75 I'm not sure how I can register that data structure when listening to the initial connection. On the client side I can listen to an `open` event, but then it seems the socket is already open. On the server side, I don't think I have any info from the client (in the `.upgrade` method of the `WebSocketTransformer` – Pacane Nov 22 '14 at 19:11
  • 1
    Nvm I think I figured it out. Once the connection is established, I can send the data structure from the client using `socket.send()` and then on the server side, I can receive it from the `listen` and associate the `socket` object to the actual data structure. – Pacane Nov 22 '14 at 19:23
1

As far as I know window.onBeforeUnload is the right event. There are some limitations what is allowed for this eventhandler. For example it is not possible to prevent window closing.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    In a modern browser when a xhr is started in an onbeforeunload/unload handler as a user navigates away from a page, connections are often closed before they can complete. I assume this is similar with a websocket. One workaround was using a synchronous xhr, but this can be pretty bad for the user experience. And synchronous xhrs are-being depreciated in most browsers. There is a new web api under development called navigator.sendBeacon(), which is designed to solve this use case. But it is only supported in some of the latest browsers. – Greg Lowe Nov 22 '14 at 10:13