4

I have a Backbone multipage app written with the use of RequireJS. Since it's multipage I decided not to use a router as it got too messy. I've tried multiple ways of creating a singleton object to be used throughout the app

var singletonModel= Backbone.Model.extend({

}),
return new singletonModel;

For the above I'm just referencing the singletonModel model in my class using the define method and then calling it as is

this.singleton = singletonModel;
this.singleton.set({'test': 'test'});

On a module on my next page when I then call something similar to

this.singleton = singletonModel;
var test = this.singleton.get('test');

The singleton object seems to get re-initialized and the test object is null

var singletonModel= Backbone.Model.extend({

}, {
    singleton: null,
    getSingletonModelInst: function () {
        singletonModel.singleton =
            singletonModel.singleton || new singletonModel;
        return singletonModel.singleton;
}

});
return singletonModel;

For the above I'm just referencing the singletonModel model in my class using the define method and then calling it as is

this.singleton = singletonModel.getSingletonModelInst();
this.singleton.set({'test': 'test'});

On a module on my next page when I then call something similar to

this.singleton = singletonModel.getSingletonModelInst();
var test = this.singleton.get('test');

Again it looks like the singleton object is getting re-initialized and the test object is null.

I'm wondering if the issue is because I'm using a multi-page app with no router so state is not been preserved? Has anyone tried using a singleton object in a multi-page app before? If so did you do anything different to how it's implemented on a single-page app?

Thanks, Derm

dermd
  • 167
  • 3
  • 13
  • I'm pretty sure the issue is that AMD modules will only hold state across a single page so the singleton is getting re-initialized when I move pages but be interesting to see if anyone's come across this before or has any other approaches. – dermd May 30 '13 at 21:32
  • you can visit this application structure that i have created using require.js and Backbone.js https://github.com/tryout5/Intermediate-Backbone-Arc Hope this might help you! – Ashwin Hegde May 31 '13 at 11:32

3 Answers3

9

Bart's answer is very good, but what it's not saying is how to create a singleton using require.js. The answer is short, simply return an object already instanciated :

define([], function() {

   var singleton = function() {
      // will be called only once
   }

   return new singleton()
})

Here we don't have a singleton anymore :

define([], function() {

   var klass = function() {
      // will be called every time the module is required
   }

   return klass
})
julesbou
  • 5,570
  • 4
  • 31
  • 36
3

It's may sound a little ... but, you doing a multi-page application, so when you move to next page, a whole new document was loaded into the browser, and every javascript on it will be loaded too, include require.js and your model. so the require.js was reloaded, and it create your model again, so you got a different model than you thought.

If above was true, my opinion is your model will "live" on a single page, when you jump to then next page, that model was "kill"ed by browser. so If you want see it again, store it on somewhere else, maybe server or localstroe, on the former page. and in the next page load it back from server or localstore, and wrap it into a Backbone model, make it "live" again.

Hetfield Joe
  • 1,443
  • 5
  • 15
  • 26
  • Apologies clean forgot to come back here to document my experience. You're exactly correct - the singleton lives on for a specific page but is reloaded and re-instantiated when I move pages. For the moment I'm using an encrypted cookie to store the info I need across multiple pages. – dermd Jul 19 '13 at 14:05
0

Here is how I implemented a singleton in a recent Backbone/Require application. State is remembered across any number of views.

instances/repoModel.js

define(['models/Repo'],
    function(RepoModel){
        var repoModel = new RepoModel();

        return repoModel;
    }
);

models/Repo.js

define(['backbone'],
    function(Backbone){

        return Backbone.Model.extend({
            idAttribute: 'repo_id'
        });
    }
);

views/SomePage.js

define(['backbone', 'instances/repoModel'],
    function(Backbone, repoModel) {

        return Backbone.View.extend({
            initialize: function() {
                repoModel.set('name', 'New Name');
            }
        });
    }
);
Bart
  • 6,694
  • 6
  • 43
  • 53
  • Thanks Bart. This looks to be the same thing as in my first sample. Couldn't you get rid of the instance class and instead of return Backbone.Model.extend({ idAttribute: 'repo_id' }); do something like var repo = Backbone.Model.extend({ idAttribute: 'repo_id' }); return new repo; – dermd May 30 '13 at 21:27
  • You certainly could. I structured my app out this way to keep all models actually under the models directory. Imagine a `user` model. You might use it many times for different users, but then use the same model for the logged in user, which you'd want to be a singleton. This kind of scenario is where separating the `model` and `instance` helps. – Bart May 30 '13 at 21:53