Re: [ClojureScript] Consequences of not closing channels in browser?
On Saturday, August 30, 2014 8:24:19 PM UTC-5, Daniel Kersten 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 dh...@dhruvbhatia.com 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 clojurescrip...@googlegroups.com. To post to this group, send email to clojur...@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. This was so extremely helpful, thanks! -- 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Consequences of not closing channels in browser?
Perfect! Closing the channel is simpler than using a kill channel (in the cases when its possible to do this - if something else owns the channel then you can't use this method of course). On 1 September 2014 11:41, Dhruv Bhatia dh...@dhruvbhatia.com wrote: Thanks for reviewing my solution Daniel. I can confirm that cljs.core.async.impl.channels.ManyToManyChannel.closed gets set to true after my component is unmounted and (! subscriber-ch)subsequently returns nil, so it looks to be working as expected! Cheers, Dhruv Bhatia On Aug 31, 2014, at 8:48 PM, Daniel Kersten dkers...@gmail.com wrote: I assume that (! subscriber-ch)will return nil when subscriber-ch is closed? I vaguely remember this to be the case, though have not tested it. If it does, then your way looks good to me. -- 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Consequences of not closing channels in browser?
I use a mixin for this purpose all the time! (defmixin go-loop-aware (init-aware [owner] {:chans {:mounted (async/chan)}}) (will-unmount [owner] (async/close! (om/get-state owner [:chans :mounted]))) (go-loop-aware [owner read-chan callback] (when (exists? js/window) (let [mounted (om/get-state owner [:chans :mounted])] (go-loop [] (when-some [v (first (async/alts! [read-chan mounted]))] (callback v) (recur))) I like the kill channel solution better personally since like Daniel point out, it doesn't require the read-chan to be owned or controlled by the component. When [:chans :mounted] is closed, the go-loop exits. I always use when-some over when-let here since when-let would close the go block if false was ever submitted to your read channel, whereas when-some only evaluates (not= nil) -- 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Consequences of not closing channels in browser?
I assume that (! subscriber-ch)will return nil when subscriber-ch is closed? I vaguely remember this to be the case, though have not tested it. If it does, then your way looks good to me. On 31 August 2014 02:40, Dhruv Bhatia dh...@dhruvbhatia.com wrote: 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 dkers...@gmail.com 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 dh...@dhruvbhatia.com 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. 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
Re: [ClojureScript] Consequences of not closing channels in browser?
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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Consequences of not closing channels in browser?
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 dh...@dhruvbhatia.com 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Consequences of not closing channels in browser?
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 dkers...@gmail.com 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 dh...@dhruvbhatia.com 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript. -- Note that posts from new members are
Re: [ClojureScript] Consequences of not closing channels in browser?
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. On 12 July 2014 02:24, Roberto Oliveros robertoolive...@mac.com wrote: I'm using Om for the client side and through the lifetime of the application many components gets mounted/unmounted. When mounted, various channels are opened (in go blocks). And I'm planning to use IWillUnmount to close them too. But first, my questions are: What happens to unclosed channels? Do the resources they used get released? Not closing channels (when unmounting components) can degrade the browser performance in the longrun? Thanks. -- 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Consequences of not closing channels in browser?
I'm using Om for the client side and through the lifetime of the application many components gets mounted/unmounted. When mounted, various channels are opened (in go blocks). And I'm planning to use IWillUnmount to close them too. But first, my questions are: What happens to unclosed channels? Do the resources they used get released? Not closing channels (when unmounting components) can degrade the browser performance in the longrun? Thanks. -- 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 clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.