Thanks a lot.

I managed to create a solution which doesn't require a separate kill-channel. 
It seems to be side-effect free and cleans up as expected, though I'm still 
quite new to Clojurescript and core.async so I may be wrong!

; UTIL.CLJS
; PUB/SUB SETUP

; create a global events-ch channel which is used to transport messages
(def events-ch (chan))

; broadcaster allows us to subscribe to certain topics within events-ch
(def broadcaster
  (pub events-ch #(:topic %)))

; MY-COMPONENT.CLJS

; my-component wants to subscribe to the :login-error topic in our global 
events-ch channel
(defn my-component [app owner]
  (reify
    om/IInitState
    (init-state [_]
      {:subscriber-ch nil})
    om/IDidMount
    (did-mount [_]
               (let [broadcaster util/broadcaster
                     subscriber-ch (chan)]
                 (do
                   (om/set-state! owner :subscriber-ch subscriber-ch)
                   (sub broadcaster :login-error subscriber-ch)
                   (go-loop []
                            (when-let [message (:message (<! subscriber-ch))]
                              (do-something message)
                              (recur))))))
    om/IWillUnmount
    (will-unmount [_]
                  (let [broadcaster util/broadcaster
                        subscriber-ch (om/get-state owner :subscriber-ch)]
                    (do
                      (js/console.log "unsubing/closing channel" subscriber-ch)
                      (unsub broadcaster :login-error subscriber-ch)
                      (close! subscriber))))
    om/IRenderState
    (render-state [this state]
            ...



On Aug 31, 2014, at 11:23 AM, Daniel Kersten <[email protected]> wrote:

> Something like this:
> 
> (defn component [data owner]
>   (reify
>     om/IInitState
>     (init-state [_]
>       (let [chan (chan)]
>         {:chan chan
>          :kill (chan)
>          :pub  (pub chan first)}))
> 
>     om/IWillMount
>     (will-mount [_]
>       (let [pub (om/get-state owner :pub)
>             chan (chan)
>             kill (om/get-state owner :kill)]
>         ; If using pub/sub, need to subscribe
>         (sub pub :foo chan) 
>         (go-loop []
>           (let [[v c] (alts! [chan kill])]
>             (when-not (= c kill)
>               (do-something v)
>               (recur))
>             ; If using pub/sub, need to unsubscribe:
>             (unsub pub :foo chan)))))
> 
>     om/IWillUnmount
>     (will-unmount [_]
>       (put! (om/get-state owner :kill) :quit))
> 
>     om/IRenderState
>     (render-state [_ {:keys [chan]}]
>       (dom/div {:onClick #(put! chan [:foo "Hello"])}
>         "Click me to send [:foo \"Hello\"]"))))
>             
> 
> 
> On 30 August 2014 16:08, Dhruv Bhatia <[email protected]> wrote:
> On Sunday, 13 July 2014 01:46:41 UTC+10, Daniel Kersten  wrote:
> > Channels are cheap, but unless they get garbage collected (and I assume not 
> > closing them will prevent this), they will still take up some resources.
> >
> >
> > Related and important is that you shut down any go blocks that you create 
> > in IWillMount, especially if they take from a channel which may still be 
> > receiving data (eg: through mux or pub/sub). If you don't shut these down, 
> > they will continue to run even after the component has unmounted and if the 
> > component is later mounted again, you will have multiple go blocks doing 
> > the same thing! Besides using resources, this can actually be dangerous if 
> > you are accessing owner inside the go block (eg to set local state) as you 
> > may end up accessing an unmounted owner. The simplest solution is having a 
> > kill channel that you listen on using async/alt that gets closed in the 
> > IWillUnmount and that terminates the go block.
> 
> Thanks for the explanation. Would you be able to provide a code example that 
> demonstrates how to properly clean up a pub/sub watcher within a component's 
> IWillUnmount lifecycle method?
> 
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/clojurescript.
> 
> 
> -- 
> Note that posts from new members are moderated - please be patient with your 
> first post.
> --- 
> 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/_a5dPeElqG4/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to 
> [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/clojurescript.

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to