How to subscribe and unsubscribe to a resource over websockets?

486 views
Skip to first unread message

Chet Corcos

unread,
Oct 27, 2015, 4:22:04 AM10/27/15
to Elm Discuss
I'm curious how pub/sub works with the Elm architecture and if there are any examples. I suppose a view might initialize a subscription to some data in the init method with an effect task. And then all views would need a 4th function to cleanup and unsubscribe from any side-effects. Does this sound reasonable? Or is there a better way of doing it?

P.S. I'm learning Elm and recreating the same patterns in Coffeescript. I'd really like appreciate some feedback on it: https://github.com/ccorcos/elmish

Thanks

Chet Corcos

Peter Damoc

unread,
Oct 27, 2015, 5:35:16 AM10/27/15
to Elm Discuss
Hello, 

Have you had a chance to take a look at elm-socketio? 

Maybe one of the examples you find there can help you better understand how to accomplish what you want to do.


--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
There is NO FATE, we are the creators.
blog: http://damoc.ro/

Max Goldstein

unread,
Oct 27, 2015, 11:20:17 AM10/27/15
to Elm Discuss
Thanks for recommending my library Peter!

I wrote elm-socketio without thinking much about start-app or elm-effects, which it sounds like our friend is using. You'd have to pass the socket tasks out to the effect handler, but not before you hooked up Signal.send and Task.andThen to send the socket (and incoming data) back in as action. I'm sure it's possible, but it might not be obvious if you're new to Elm.

Chet Corcos

unread,
Oct 28, 2015, 4:09:28 AM10/28/15
to Elm Discuss
Hmm. Interesting. Those examples don't seem to follow the Elm Architecture... I couldn't really follow them -- I'm new to Elm. What'd hard for me to understand is how you can abstract away the lifecycle of the socket. Suppose you have chat component that gets a chatroom id. I could render a list of these chatrooms. But how do I make sure to unsubscribe from certain messages when I remove and item from the list? I'm not sure how to do that unless the list has to keep track of it... Does that make sense?

Max Goldstein

unread,
Oct 28, 2015, 10:23:28 AM10/28/15
to Elm Discuss
As for the Elm Architecture, please see this example: https://gist.github.com/mgold/c7832f9197ff3e931152

As for subscribing and unsubscribing, it's a bit trickier. The library was really designed for the case where you want a constant connection to the server and all (or most) messages are relevant. If you're interfacing with an existing Socket.io service that uses rooms and complex subscription (which is inherently mutable), you might be out of luck, or at best, need some JS code to pass the cleaned up messages into Elm.

On the other hand, if you're writing the server too, just come up with a JSON format for messages that you can deserialize in Elm that contains information on chatrooms, etc. As a rough sketch:

type alias Model = { rooms : List String, ... }
type alias Message = {room : String, text : String, senderID: Int, ...}
type alias Action = Received Message | ...

update action model =
  case action of
    Received {room, text} -> if not (List.member room model.rooms) then model else ...

Hope that helps.

Chet Corcos

unread,
Oct 28, 2015, 7:04:30 PM10/28/15
to elm-d...@googlegroups.com
Interesting. I like this a lot actually. Rather than let each resource subscribing and unsubscribing with the view lifecycle, you just let the views describe the resources they want. Reminds me of Relay and GraphQL. I'm curious how you'd implement that. It would have to be something parallel with the effects and the model in init and update. That way you could merge resource requests and just make one large request of all the chatrooms you need. And that large request is just another stream.

The thing that gets a little tricky here is network data usage and setting up the proper event listeners. For example: (1) you wouldnt want to send the entire state to the server -- you'd only want to send what has changed and reconstruct it. This way you use the minimal amount of data. This could be a simple wrapper though. (2) on the server, you must register users to be subscribing to some chatrooms. That is, you'd have an array of signals that all point to the associated websockets. So when a new message comes in, you can map over this array to dispatch the methods. But when a new request comes in from the server, we have to compute the difference between the new subscription request and old the subscriptions and remove the event listeners appropriately... idk this just seems kind of awkward. I suppose we could structure the server much in the same way we construct the UI... hmm. I'll have to do some more thinking on this.




--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/r_z_QhTj4wE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.

Thomas Weiser

unread,
Oct 29, 2015, 4:05:20 PM10/29/15
to elm-d...@googlegroups.com
Hello Chet,

as subscribing/unsubscribing are inherently effectful tasks, they
shouldn't get abstracted away.

So, like you mentioned, the list of chatrooms should keep track of the
current subscriptions together with whatever data is needed to later
unsubscribe again.

Of course this pattern only makes sense when the communication layer has
a means to cancel prior subscriptions. As Max pointed out this is not
the case for elm-socketio. But then this pattern will probably be
applied to a layer above that. As long as it happens in Elm code you
will most certainly execute a task (trigger an effect) to stop receiving
information, which you are no longer interested in.

Chet Corcos

unread,
Oct 29, 2015, 6:50:19 PM10/29/15
to elm-d...@googlegroups.com
So I talked to Evan for a while about this last night actually. I think the solution lies in creating some kind of data structure called a "Resource". The results of the resource can get mapped over and routed back to the proper component. But the description of the resource stays the same. This way you can combine the resources on its way up the heirarchy and at the top, you have this stateless representation of the resources you need. Sync this array or resource requests with the server over websockets and you're good. Now the server needs to manage how to mutate event listeners in response to new states... still working on this idea, but I think its in the right vein...

--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/r_z_QhTj4wE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages