5 ms·
It sounds like there needs to be a garbage collector for backbone. Is there any projects out there dealing with 'Zombie' objects?
by togasystems 15y ago
It sounds like there needs to be a garbage collector for backbone. Is there any projects out there dealing with 'Zombie' objects?
- rdpfeffer 15y agoI think the problem has more to do with event bindings and how they cause references between objects in the JS runtime than it does with backbone. However we found that consistency and patterns were a simple enough solution for this problem. It just takes a bit of double checking is all when you are writing code. In comparison, I would say objective-c's retain/release patterns are a much more difficult to understand.
- derekcicerone 15y agoSince you usually only want the listeners attached when a view is actually part of the page's DOM, would it be possible to monitor the DOM for when the view is removed and do cleanup automatically based on a DOM event? (perhaps using the mutation DOM events http://en.wikipedia.org/wiki/DOM_Events http://en.wikipedia.org/wiki/DOM_Events)
- rdpfeffer 15y agoMaybe, but that would mean you also have a reference from the dom element back to your JS object that was bound in the first place. I've been wrong plenty of times though, would be cool to see someone give it a try.
- Joeri 15y agoExtjs solves this by abstracting the dom. When you want to remove a component from its parent, you call the remove() method and it handles all the dom unbinding behind the scenes. You never interact with the dom api directly. Adding content is done by calling the add() method of the parent and passing it a child component instance. It also decouples rendering from component construction. You can have an entire component hierarchy with operational events and fully interactive from the code's perspective, that isn't rendered to the dom at all.
- malandrew 15y agoAdd a destroy() method to your views that unbinds any events bound in the initialize() method or other methods and then calls remove() on `this` (for every .on() have a corresponding .off()). Call this .destroy() method instead of remove(). Most of the time this should free up all references so the javascript GC can sweep and clean up old views. Another option is to reuse the same views and never re-render the same view twice.
- jashkenas 15y agoAs an additional note, you'll only run into "zombie event" problems if you have to throw away views and models that are bound together at different times. If you tend to throw away models and their corresponding views together, then you never have to unbind anything, and it's all GC'd by JavaScript naturally.
- rdpfeffer 15y agoNice. Yeah, I don't know enough about GC and how it does detecting cycles, but I can see how that would fix the problem. As We haven't addressed local caching of data yet, we're still just holding everything in memory. Therefore, for us many of our models never get thrown away. Definitely Something to watch out for.
- markkanof 15y agoHas anyone seen any good information about using the Chrome Profiles tool (or similar) to track down these 'zombie' objects?
- EdwardMSmith 15y agoI do this, but I don't do anything special. I just take a snapshot, enter and exit the view, say 5 times, then take another snapshot. Switch over to showing deltas and look for your objects in the list.
- snprbob86 15y agoHere's what we did: 1) Derive all views from our own BaseView class (which derives from Backbone.View) 2) BaseView's initialize function sets $el.data('view', this) 3) BaseView provides a `dispose` method which with some default logic for event handlers added in a particular way. 4) We overrode jQuery.cleanData to check for the view data on each element and call dispose on them. This ensures every view is cleaned up when it is removed from the DOM via jQuery. 5) Use $.fn.remove and $.fn.detach appropriately. This works splendidly in practice.
- sgk284 15y agoI'm snprbob86's co-founder at Thinkfuse. Here's our actual jQuery cleanData wrapper (in coffeescript): https://gist.github.com/2046371 https://gist.github.com/2046371 jQuery.cleanData = _.wrap jQuery.cleanData, (cleanData, elems) -> for elem in elems $(elem).data('view')?.dispose() cleanData.apply @, arguments That lets jQuery handle garbage collecting automatically for us whenever the Backbone view's corresponding element is removed from the page. Just make sure your base view constructor sets the 'view' data attribute on it's element.
- funkah 15y ago> initialize function sets $el.data('view', this) Whoa, you can do that? Huh.