0

Trying to get a handle on memory management with Backbone by using the heap snapshot tool in Chrome. There's a back button on a view which when clicked will switch the current view with a new one via a backbone router.

I take a snapshot on the initial page, navigate to the page with the back button, click the back button and take another snapshot. I'd expect heap snapshot to be identical using the comparison option. However old models/collections seemingly aren't being cleared (they are highlighted in white in the snapshot i.e. still accessible via the root of the graph). Also it looks like the views themselves aren't being removed either(same white highlight in the snapshot).

I've linked a diagram to aid the explanation (https://i.stack.imgur.com/mlN2I.jpg). Say view V1 nests three views of which V2 contains a model M1, V3 holds model M2 and V4 holds a backbone collection C1. M1 listens to a change to M2 and updates itself accordingly. In order to properly remove view V1 the following are done:

  • Call Backbone.View.Remove on V1 and all its child views (and the child views of those children if they exist)
  • Call Backbone.Events.StopListening on all models (and the child models of those models if they exist)

Is this enough to completely clear the view? It seems like most resources online discuss proper disposal of backbone views but not its models/collections.

Any help would be much appreciated. Thanks.

user3710396
  • 151
  • 2
  • 6

2 Answers2

2

Use this method for clearing the child views and current views from memory.

//FIRST EXTEND THE BACKBONE VIEW....
//Extending the backbone view...
Backbone.View.prototype.destroy_view = function()
{ 
   //for doing something before closing.....
   if (this.beforeClose) {
       this.beforeClose();
   }
   //For destroying the related child views...
   if (this.destroyChild)
   {
       this.destroyChild();
   }
   this.undelegateEvents();
   $(this.el).removeData().unbind(); 
  //Remove view from DOM
  this.remove();  
  Backbone.View.prototype.remove.call(this);
 }



//Function for destroying the child views...
Backbone.View.prototype.destroyChild  = function(){
   console.info("Closing the child views...");
   //Remember to push the child views of a parent view using this.childViews
   if(this.childViews){
      var len = this.childViews.length;
      for(var i=0; i<len; i++){
         this.childViews[i].destroy_view();
      }
   }//End of if statement
} //End of destroyChild function


//Now extending the Router ..
var Test_Routers = Backbone.Router.extend({

   //Always call this function before calling a route call function...
   closePreviousViews: function() {
       console.log("Closing the pervious in memory views...");
       if (this.currentView)
           this.currentView.destroy_view();
   },

   routes:{
       "test"    :  "testRoute"
   },

   testRoute: function(){
       //Always call this method before calling the route..
       this.closePreviousViews();
       .....
   }


   //Now calling the views...
   $(document).ready(function(e) {
      var Router = new Test_Routers();
      Backbone.history.start({root: "/"}); 
   });


  //Now showing how to push child views in parent views and setting of current views...
  var Test_View = Backbone.View.extend({
       initialize:function(){
          //Now setting the current view..
          Router.currentView = this;
         //If your views contains child views then first initialize...
         this.childViews = [];
         //Now push any child views you create in this parent view. 
         //It will automatically get deleted
         //this.childViews.push(childView);
       }
  });
Robins Gupta
  • 3,143
  • 3
  • 34
  • 57
0

There are a few answers to the similar questions already.

The old one here and a bit fresh answer even with video

Community
  • 1
  • 1
loislo
  • 14,025
  • 1
  • 28
  • 24