adampetrie
adampetrie

Reputation: 1150

Reusing Backbone Views

I am writing a Backbone app that users move through in a linear fashion. The app works like a tv show whereby the narration leads the user through an episode from scene to scene.

To accomplish this goal, I have one parent Episode view that is responsible for loading the correct Scene view at the correct time. I am happy with how this functions so far.

I need to add in the ability for users to skip from scene to scene at their leisure. Possibly viewing the same scene multiple times throughout the life of the app. My question is whether or not I should be creating a new Scene view every time I load the same scene or if I should create an instance of the scene and then just re-use it when the user loads it a second, third, or fourth time.

The sample below shows how I've gone about reusing the scenes so far.

loadSceneView: function()
{
    var sceneIndex = this.model.getCurrentIndex();

    if(this.scenes[sceneIndex])
    {
        this.scenes[sceneIndex].render();
        console.log('Scene: ' + sceneIndex + ' already loaded. Reusing');
    }
    else
    {
        console.log('Loading Scene: ' + sceneIndex);

        switch(sceneIndex)
        {
            case 0:

                this.scenes[sceneIndex] = new cith.Views.Scene1();
                break;

            case 1:

                this.scenes[sceneIndex] = new cith.Views.Scene2();
                break;

            case 2:

                this.scenes[sceneIndex] = new cith.Views.Scene3();
                break;
        }
    }

    this.currentScene = this.scenes[sceneIndex];
    this.listenTo(this.currentScene, 'scene:ended', this.goToNextScene);

    $('#scene').html(this.currentScene.el);
}

Basically, if the scenes array has an index matching the current sceneIndex just load that view into the dom. Otherwise, create it, keep the reference to it in the scenes array and load it into the DOM.

Can anyone help me to identify the pro's and cons of this approach? Specifically I am concerned with the best performance possible as well as avoiding memory leaks as a side-effect of keeping references to these objects that my (or may not) get used again.

Thanks.

Upvotes: 3

Views: 728

Answers (3)

PhD
PhD

Reputation: 11334

What's stopping you from just creating all the views up front and just fetching them from the cached array at run time? Are your views really that resource intensive? If so, caching makes sense and your above approach is good. If not, I'd either go with creating them on the fly (no caching/reuse) or create all of them upfront (cache references in an array) and just fetch them at run time. If you are concerned about performance/memory leaks usage, you can use something like the following:

   var dispatcher = _.clone(Backbone.Events); //Event-bus for all the views to talk to each other

/*
 * Create a BaseView for all classes to inherit from. "Intercept" Backbone's constructor
 * by providing a hook for any custom initialization that needs to be done across views.
 */
    //reference to Backbone.View's constructor
    var ctor = Backbone.View;
    //extend Backbone.View
    var BaseView = Backbone.View.extend({
        //override the constructor property
        constructor: function(options){
            //call Backbone.View's constructor (ctor) and just proxy the arguments to it
            ctor.apply(this, arguments);
            //perform initialization here
            dispatcher.on('close',this.close, this);
        },

        //Adding a custom close method inheritable by all 'children' of BaseView. 
        close: function(){
            //if an onClose 'handler' is defined by the class execute it - for any custom 'close' logic to be called
            if(this.onClose)
                this.onClose();

            this.off();
            this.undelegateEvents();
            this.remove();
        }
    });

You create a 'Base class' for all your views with a close() method that unbinds the view(s) from the corresponding model(s) and events and removes itself from the view/DOM. This could be used in tandem with your caching strategy, or you need not cache anything at all if things tend to change (concurrently by some other user and you don't want to implement polling or haven't implemented a server side push). I use this strategy if/when I know I'll have too many objects that could lead to memory usage/leaks that could slow performance.

Hope this helps :)

Upvotes: 1

obmarg
obmarg

Reputation: 9559

Unless you're building a really resource intensive app this is probably premature optimisation. I'd just go with whatever approach is easiest, and optimise the code later if performance proves to be a problem.

Aside from that, there's probably not an absolute correct answer to this. There's several factors you need to weigh up:

  • The time it takes to (re)construct a scene.
  • The amount of memory that'd be used by inactive scenes
  • How often scenes are going to be used
  • How many scenes there are in total

If constructing a scene is quick enough that a user won't notice, and doesn't involve downloading or loading extra resources then it would probably be fine to just re-render views every time. However if rendering takes a noticeable period then maybe you should think about keeping views around. Likewise, I'd definitely keep a cache of resources that might be re-used.

On the other hand, I'd guess your views are going to be using really small amounts of memory (particularly compared to the gigs of RAM most machines & phones have these days) so keeping them in memory probably isn't going to be much of an issue (unless you think you'll end up with thousands of them still in memory - really depends how many views you think the user will interact with in a single session)

If you're really concerned about using too much memory, then you could always just cache some of the views rather than all of them - either by how likely to be re-used they are, or some sort of 'most recent views' scheme where the most recent 20 (or whatever) views are stored in memory, and the rest are constructed when they're needed. However this is a bit more complicated, and quite possibly overkill.

Upvotes: 4

Labib Ismaiel
Labib Ismaiel

Reputation: 1340

actually, you obviously know it but need confirmation, what you are suggesting is what should be done, the view should be created once only and then rendered when needed, as for memory needs it only depends on the total number of scenes you have, but still, I can't imaging a case where a browser would give up on because it's exhausting memory, so, in my humble opinion, your work is very good, and that's how I would do it.

Upvotes: 1

Related Questions