Let me add that, profiling this in Chrome has shown a steady growth of the number of ManyToManyChannel objects when I do a lot of resizing, but Garbage collection does clean them up nicely.
On Monday, January 13, 2014 1:10:15 PM UTC-8, David Pidcock wrote: > I've been playing around with Om recently, and started down a rabbithole > towards a drag-drop implementation. > > In my (toy) application, I have a couple of lists of items which I want to > drag between. Before stumbling on Om and React, I was using a > goog.fx.DragListGroup, and listening to the events. But binding data back to > sub-components of the app was starting to look onerous. > > Om to the rescue! > > The lists are in app-state and mutations on them cascade nicely to the > sub-components. Great. > > So my first thought was to try to integrate DragListGroup somehow (after all > - that code is already written). Unfortunately, React doesn't like DOM > manipulation outside it's lifecycle (it's possible, but much harder to do in > idiomatic Om). > > Fortunately, David Nolen threw a sortable example together. > > Building on that example, I now have my "master app" component creating some > core.async channels, which it then passes down to sub-components. These > components can register for drag-events within their visible bounds. > > So here's my problem : when the bounds of a component change (i.e. it get's > re-sized), the existing channel still only delivers events to the old bounds. > > I 'solved' this by untapping the old channel, creating a new channel with a > filter for the new bounds and listening to it. > > This seems .. unwieldy. > > ; state is either current or previous state , depending on whether this > ; is called from did-update or did-mount. > > (defn listen-bounds [owner state opts ref-node] > (when-let [container (om/get-node owner ref-node)] > (let [ dims (-> container gstyle/getSize gsize->vec) > disperser (disperser opts) > drag-chan (:drag-target-chan state) > new-bounds (bounds container) > track-fn (fn [evt] (om/set-state! owner :last-evt evt)) > ] > (if (= (:bounds state) new-bounds) > (do > (if (nil? drag-chan) > (create-listener disperser new-bounds track-fn) > drag-chan) > ) > (do > (when-not (nil? drag-chan) > (untap disperser drag-chan) > (close! drag-chan)) > > (om/set-state! owner :bounds new-bounds) > (let [new-drag-chan (create-listener disperser new-bounds track-fn)] > (om/set-state! owner :drag-target-chan new-drag-chan) > new-drag-chan) > ))))) > > > > (defn directed-event-chan [bounds] > (filter> > (bound-filter bounds) > (chan))) > > (defn create-listener [disperser bounds f] > (let [drag-target-chan (directed-event-chan bounds)] > (tap disperser drag-target-chan) > (go (while > (when-let [event (<! drag-target-chan)] > (f event) > event > ))) > drag-target-chan > )) > > > So two questions : > 1. I couldn't tell if untapping a channel also effectively closes it. Is > (close! ..) necessary here? > 2. Is there some way to avoid this churn? Would using an atom in > (directed-event-chan [@bounds] get me a dynamic filter? > > > As an aside : A lot of the core-async tutorials use (go (while true ... > I haven't gotten into the implementation, but if all channels in a go loop > are closed, is that code still taking up memory somewhere? > > I erred on the safe side (perhaps at the expense of readability) by using > (go (while (when-let ... ) and returning the value of the last read from > the channel. When the channel returns nil upon close, this is guaranteed to > exit. -- 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.
