Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling global application state (not variables as such) in CommonJS projects (specifically Browserify)

Using Browserify with Backbone projects, and I'm just wondering if anyone's got any advice/pointers on how to handle global state. By global state, I don't necessarily mean global variables, but I mean values that are application-wide, ie. currently logged in user, the app router (for navigating from Views), an Events object (for communication around the application).

Apart from passing these things into each View/module that might need them, is there a simpler way?

If we use Backbone as a working example, I have code like:

signupComplete: function() {
    swap(regions.content, new views.completeSignup({
        model: this.currentUser(),
        router: this
    }));
},

this lives in my app-router.js and as you can see, it's passing the router itself into the instantiated View.

Is this kind of practice recommended in CommonJS style applications, where dependencies are kept local and "global" is advised against.

Not sure if there's a right answer here, just looking for some different approaches people have taken in this, relatively, young concept in building client-side applications with Browserify...

like image 350
benhowdle89 Avatar asked Oct 20 '22 07:10

benhowdle89


2 Answers

How about a singleton pattern type of thing?

var router;

module.exports = function () {
  if (!router) router = new Router();
  return router;
};
like image 159
mrappleton Avatar answered Oct 24 '22 00:10

mrappleton


Here's an approach that avoids the boilerplate of passing state down view trees, but still gives the option for local state for testing or sub-systems. TL;DR: sling it on View.prototype, override via constructor where necessary.

In views (and views are the only place I see this as necessary) we access the user via this.user, which will be from the prototype unless an instance is passed an user in the constructor.

var View = Backbone.View.extend({
  constructor: function(opts) {
    if(opts.user) this.user = opts.user;
    if(opts.vent) this.vent = opts.vent;

    Backbone.View.apply(this,arguments);
  }
});

In a production boot script we pass any app-wide state to the prototype:

var user = new User;
var vent = new Vent;

View.prototype.user = user;
View.prototype.vent = vent;

In some sub-system with a local version of any of these bits of state, pass it in and it'll be used in preference to the prototype property:

var subVent = new Vent;
var subA = new SomeView({name: "subA",vent: subVent});
var subB = new SomeView({name: "subB",vent: subVent});

In testing:

var mockVent = new Vent;
toTest = new SomeView({name: "testA",vent: mockVent});

Here's a live demo of the technique.

like image 36
timruffs Avatar answered Oct 24 '22 01:10

timruffs