(newbie) om - clarity question: do I need to unsubscribe async channels?

128 views
Skip to first unread message

Colin Yates

unread,
Oct 30, 2014, 2:01:05 PM10/30/14
to clojur...@googlegroups.com
(om/core.async newbie warning)

I see a common pattern (including in the om tutorials) of using channels to communicate. Specifically I see code similar to:

[code]
om/IWillMount
(will-mount [_]
(let [nav (om/get-shared owner :nav-chan)]
(go (loop []
(let [page (<! nav)]
(om/transact! app :page (fn [x] page))
(recur))))
[/code]

What happens when that component is unmounted? Do I need to stop listening to that channel and if so how do I do that?

I am not claiming there is a problem, I am simply asking if there is a potential problem and for clarity on the mechanics.

For context, I am mounting/unmounting quite a bit as they navigate through the app.

Thanks!

Daniel Kersten

unread,
Oct 30, 2014, 4:24:33 PM10/30/14
to clojur...@googlegroups.com
Yes, you should terminate the go block in will-unmont, otherwise if your component is mounted multiple times, you will end up with multiple go blocks consuming from the channel. If you are transacting on a cursor, then this will just eat up resources, but if you are accessing owner (eg to get/set local state) then you also risk accessing stale react components.

I personally use an om-tools mixin to handle both subscribing and unsubscribing to core.async pubs. This way I don't have to remember to unsubscribe in unmount myself.


--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Colin Yates

unread,
Oct 30, 2014, 4:33:48 PM10/30/14
to clojur...@googlegroups.com
I assumed so but thought I should check that there wasn't some fancy
garbage collection thing happening.

Do you happen to have a quick example of how to use the om-tools mixin
to automatically unsubscribe?

Thanks!
> You received this message because you are subscribed to a topic in the
> Google Groups "ClojureScript" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojurescript/XTdL_KHuvG8/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to

Daniel Kersten

unread,
Oct 30, 2014, 5:37:59 PM10/30/14
to clojur...@googlegroups.com
There was some discussion about this here https://groups.google.com/forum/#!topic/clojurescript/_a5dPeElqG4 which might help get you started.

What I do is basically something like this (untested so may need some work):

(defmixin listener
  (will-unmount [owner]
    (async/close! (om/get-state owner :listener-chan)))
  (listen [owner callback]
    (let [my-chan (async/chan)]
      (go-loop []
        (if-let [data (async/<! my-chan)]
          (callback data)
          (recur)))
      (om/set-state! owner :listener-chan my-chan)
      (async/tap global-mult my-chan))) ; note #1

and used like this:

(defcomponentk test-component []
  (:mixins listener)
  (will-mount [_]
    (listen (fn [data] (println "Got data:" data))
  ...)

Then instead of calling om/build, you would do (->test-component data)

note #1:
global-mult is obtained using (async/mult sender-ch), where sender-ch is the channel you put data on that you want to distribute to your components. How sender-ch and global-mult is passed to your components is up to you (you could use Om's shared state, for example).

Also, you don't have to use a mult if you don't want to multicast data to all your listeners (or you could use many purpose-specific mults and pass it into listen). In my real code I use pub/sub.

Hopefully this will give you some ideas to get you started.

Colin Yates

unread,
Oct 30, 2014, 5:43:03 PM10/30/14
to clojur...@googlegroups.com

Thanks Daniel.

Daniel Kersten

unread,
Oct 30, 2014, 6:20:42 PM10/30/14
to clojur...@googlegroups.com
No problem! Hope it helps.

A minor correction - the mixin function listen is actually called like this:

(.listen owner (fn ...))

You can see documentation on using mixins in the om-tools docs.
Reply all
Reply to author
Forward
0 new messages