Backbone.EventBinder: Better Event Management For Your Backbone Apps

One of my most popular blog posts in recent history is my Zombies! RUN! post where I outline the possibility and problem of memory leaks and “zombie” views and other objects in Backbone applications. There’s a good chance, in fact, that if you’ve built a Backbone application, you’ve read this article already. It seems to get more traffic and more “THANK YOU!!!!” responses than any other blog post (and rightfully so, IMO). 

Down in the comments of that post, Johnny Oshika posted a link to his solution for managing events. I fell in love with that approach almost as soon as I saw it, and baked it in to Backbone.Marionette. Over the last year, then, it has grown and evolved a little and become a solution that I rely on to help me manage events in Marionette and in my backbone app development. I even baked it’s use directly in to every Marionette view, to handle the zombie view problems. I’ve had a lot of people ask how I manage zombies in Marionette, and I always point them to this solution. I’ve also had a number of people ask if they could use that solution outside of Marionette – YES! definitely. You should use this solution in any Backbone application that attached to events! 

And now it’s even easier to use this in your app, even if you’re not using Marionette.

Backbone.EventBinder

I recently extracted Backbone.EventBinder from Marionette and turned it in to it’s own repository in the MarionetteJS Github org, so that anyone and everyone building Backbone applications can take advantage of this without having to re-write it in their app.

From the EventBinder wiki:

When To Use Backbone.EventBinder

The general guidelines is that any time you have an object that is created and destroyed throughout the life of the application, and that object needs to bind to events from some other object, you should use the `EventBinder`.

Views And Memory Leaks

Views are the perfect example of this. Views get created and destroyed all the time. They also bind to a lot of different events from both the `model` and `collection` on the view. When the view is destroyed, those events need to be cleaned up. By using the built-in `bindTo` method on the view, the event handlers will be cleaned up for you. If you don’t use `bindTo` and instead use `on` directly, you’ll have to manually call `off` to unbind the events when the view is closed / destroyed. If you don’t, you’ll end up with zombies (memory leaks).

If you haven’t read them yet, check out these articles:

Custom Event Groupings

Views are not the only place that this applies, though, and not the only use case for `EventBinder`.

If you are working with handful of objects, binding to their events, and those objects can be replaced with other object instances, then an `EventBinder` would be useful. In this case, think of the EventBinder as a collection or group of events for related objects.

Let’s say you have ObjA, ObjB and ObjC. Each of these fires some events, and you want to make sure you clean up the event handlers when your code is done. This is easy with an `EventBinder`:

doStuff = {

  start: function(a, b, c){
    this.events = new Backbone.EventBinder();

    this.events.bindTo(a, "foo", this.doSomething, this);
    this.events.bindTo(b, "bar", this.anotherThing, this);
    this.events.bindTo(c, "baz", this.whatever, this);
  }, 

  doSomething: function(){ /* ... */ },
  anotherThing: function(){ /* ... */ },
  whatever: function(){ /* ... */ },

  stop: function(){
    this.events.unbindAll();
  }

}

doStuff.start(ObjA, ObjB, ObjC);

// ... some time later in the code, stop it

doStuff.stop();

Calling `stop` in this code will properly clean up all the event handlers for this use.

When To Use on/off Directly

The converse to all of this, is to say that you don’t always need to use an `EventBinder`. You can get away without it, always. But you need to remember to clean up your events when necessary.

In situations that do not need event handlers to be cleaned up, there is no need to use an `EventBinder`, as well. This may be an event that a router triggers, or that the `Marionette.Application` object triggers. For those application lifecycle events, or events that need to live throughout the entire life of the app, don’t bother with an `EventBinder`. Instead, just let the event handlers live on. When the person refreshes the browser window, or navigates to a different site, the handlers will be cleaned up at that point.

But when you need to manage your memory and event handlers, cleaning up references and closing things down without refreshing the page or navigating away from it, then `EventBinder` becomes important as it simplifies event management.

Marionette & EventBinder

The EventBinder is still a critical and foundational part of Marionette, of course. We’re in the process of changing up how Marionette’s build and deployment process works, slightly, to account for this being an external resource. But Marionette will still make heavy use of the EventBinder, as it always has. We’re also working to make sure these changes are as simple as possible for everyone – for those who just want to use some of Marionette’s building blocks, for those contributing to Marionette, for those that are new to it and want an all-in-one download of Marionette, and for the advanced users of Marionette who want piece everything together and upgrade different parts as needed.

It’s a bit of a challenge to do this, but I think we have a good plan. Be sure to keep an eye on the Marionette website in the next month or so as we head toward this.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Backbone, Backbone.EventBinder, Javascript, Marionette. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • darius

    How does this work with the events hash in a View?

    • http://mutedsolutions.com Derick Bailey

      it doesn’t, and doesn’t need to. the events hash is managed by the view already

      • darius

        Oh, so using the events hash doesn’t expose you to the risk of zombie code?

        • http://mutedsolutions.com Derick Bailey

          generally speaking, yes.

          Of course you can write code that hangs on to the DOM elements and cause zombies… but it requires a lot of effort to purposely make that happen when using a Backbone View.

          I have yet to see a zombie view instance caused by DOM events wired in from the view’s events hash.

  • http://twitter.com/daniellidstrom Daniel Lidström

    I’ve used the technique from the Zombies blog post. I like it as many others. The technique with the EventBinder seems nice too. I’m just wondering what are the benefits from the original technique with the beforeClose method?

    • http://mutedsolutions.com Derick Bailey

      they serve different purposes, and can / should be used together.

      the EventBinder is just for handling events bindings and being able to easily group them and unbind all of them in a single call.

      the onBeforeClose / onClose methods and events are still very useful when creating a base view that uses the EventBinder in a close method.

      • http://twitter.com/daniellidstrom Daniel Lidström

        Ah I see, now it makes sense. Thanks for clarifying.

  • Naresh Bhatia

    Derick,

    I like EventBinder, but somewhere between the Zombies post and this one, I am lost on how to use EventBinder with Backbone views (which is the most popular use case). Do you still recommend adding a close() method to the Backbone.View prototype and a onClose() method to the view? Also where does one store the binder object, so that binder.unbindAll() can be called on close? What is the recommended way to close child views (e.g. a parent view on a collection which has child views on the associated models). A working example would be a great addition to the Backbone.EventBinder project.

    Thanks.
    Naresh