Memory leak when filtering the underlying system

I have a filter working on my main network. Enter search in the search box and in the list of live filters. Works great, or so I thought. When I looked at the heap of memory in chrome, I can see that the memory is leaking on every lookup ... 6 megabytes 8 megabytes ... soon heap snapshots are over 100 megabytes.

I have highlighted the problem in the view below. If I comment out this.listenTo in the initialization function, I don't see any memory leaks anymore.

So my question is how to keep these event listeners and direct filtering in the collection without leaking.

var View = Backbone.View.extend({

    tagName: 'tr',

    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(this.model, 'destroy', this.remove);
    },

    events: {
        'click .edit': 'edit',
        'click .delete': 'delete',
    },

    edit: function() { /* EDIT */ },

    delete: function() {
        this.model.destroy(); //backbone
    },

    render: function () {
        var template = _.template( ProductTemplate )
        this.$el.html( template({ this.model.toJSON() }) )
        return this;
    }

})


var ListView = Backbone.View.extend({

    initialize: function()
    {
        this.collection = new Collection( Products ) //products are bootstrapped on load
    },

    render: function (terms)
    {
        this.$el.html( ListTemplate );

        var filtered = Shop.products.collection.search(terms)

        _.each(filtered, this.addOne, this)

        //append list to table
        $('#products').html( this.el )

        return this
    },

    addOne: function (product)
    {
        this.$el.find('tbody').append(
            new View({ model: product }).render().el
        )

        return this
    },

});

var Collection = Backbone.Collection.extend({

    model: Model,

    search : function(letters){

        //set up a RegEx pattern
        var pattern = new RegExp(letters,"gi")

        //filter the collection
        return this.filter(function(model)
        {
            if(letters == "") return true //if search string is empty return true
            return pattern.test(model.attributes['Product']['name'])
        });
    }


});

      

DECIDE:

This is my new search method. I am no longer filtering collection and re-rendering. I just iterate over the collection, and if the model matches the search, we fire the "show" event, if it is not in the search, we fire the "hide" event. We then subscribe to these events in the view and act accordingly.

collection search function: search: function (query) {

    //set up a RegEx pattern
    var pattern = new RegExp(query,"gi")

    //filter the collection
    this.each(function(model){
      if ( pattern.test(model.attributes['Product']['name']) ){
        model.trigger('show')
      }
      else{
        model.trigger('hide')
      }
});
}

      

New view: var ProductView = Backbone.View.extend ({

    tagName: 'tr',

    initialize: function() {
        this.listenTo(this.model, 'show', this.show);
        this.listenTo(this.model, 'hide', this.hide);
    },

    hide: function()
    {
      this.$el.addClass('hide')
    },

    show: function()
    {
      this.$el.removeClass('hide')
    },

    render: function ()
    {
        var template = _.template( ProductTemplate )
        this.$el.html( template( {data: this.model.toJSON(), Utils: Shop.utils} ) )
        return this;
    }

});

      

+3


source to share


1 answer


To expand on what @mu has already commented on, you are not deleting the views you created. They're not in the DOM, but they are still hanging in memory because they have a reference to your models (so the garbage collector won't remove them for you).

You have several options:



  • Track all views that are created with addOne

    and delete them every time it is called render

    .
  • Make your code visible / hidden rather than instantiate / destroy every time the filter criteria change. This works more, but is definitely a better solution.
+4


source







All Articles