2

I notice that my app starts to become sluggish when I change urls too many times. I suspect this is because I have the routes set up in a way that they are instantiating a new view every time the url is visited, not sure if there is another way to do this. It may be that I don't understand javascript enough.What is happening to the views that I instantiated after they are not being used anymore, or in other words when I visit a new route?

var Router = Backbone.Router.extend({
    routes: {
        '':'doSomething',
        'helloworld':'doSomethingElse'
    }
});

var app_router = new Router;

app_router.on('route:doSomething', function() {
    var thing = new SomeModel();
    new someView({model : thing});
});

app_router.on('route:doSomethingElse', function() {
    var thing = new SomeModel();
    new someOtherView({model : thing});
});

so in this simple example, if I were to click back and fourth on links <a href="#"> and <a href="#helloworld"> would there just be a build up of view and model objects? and if so would it be a problem.I would imagine that memory would be eaten up but I may just not be understanding things correctly.

Here is a screenshot of the timeline as I click back and fourth between two routes. It seems that there is a build up of listeners which I am guessing is coming from the event listeners that I have set on one of the particular views. I think it is creating new listeners on every instantiation.

enter image description here

Spencer Cooley
  • 8,471
  • 16
  • 48
  • 63

1 Answers1

4

I think you are producing "zombie" views. Thishappens when you create a view like:

new someOtherView({model : thing});

which probably contains event bindings to DOM elements. Next time when you hit the same route again, you just create another view, with new bindings, and without unbinding the events of the previous view.

Derick Bailey wrote a great article on this:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

to simplify, you have to implement a close mechanism in your views, and close them (unbind the registered events) before creating a new one.

My Backbone views usually have a close method:

close: function () {
    this.model.stopListening();
    // unbind other stuff
}

while my routers always holding references to the previously created views:

app_router.on('route:doSomething', function(id) {
    var thing = new SomeModel();
    if (this.currentSomeView) {
        this.currentSomeView.close(); // this will unbind the previously registered events
    }
    this.currentSomeView = new someView({model : thing});
 });
Akos K
  • 7,071
  • 3
  • 33
  • 46
  • Does backbone not provide a way to unload a view? Like Ext-JS [Component's destroy method](http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.AbstractComponent-method-destroy) does? I guess not, see http://stackoverflow.com/a/11534056/227299 – Ruan Mendes Aug 26 '14 at 21:59
  • This sounds like it is probably the issue, because I do have a handful event binding to DOM elements in one of the views. – Spencer Cooley Aug 26 '14 at 22:00
  • I extended my answer with an example from my own code. – Akos K Aug 26 '14 at 22:00
  • yes, if you don't implement your own `close` method, like I did. See my answer. – Akos K Aug 26 '14 at 22:01
  • as I already stated, this was an example from my code, I'm never removing the DOM elements from my page, just re-rendering them, this is why I never call `remove()`. I just gave him and idea, in which direction he should go. – Akos K Aug 26 '14 at 22:04