4

The model caching within Backbone-Relational is very good, but to load a simple model safely requires quite a bit of code. E.g.

// Try and find a model in the Cache
this.model = MyModel.find({id:id});

if(this.model){
    // Model loaded from cache, do something.
    this.doSomething();
}else{
    // Load model then do something on success.

    var self =  this;

    this.model = new MyModel({id:id});
    this.model.fetch({
        success: function(){
            self.doSomething();
        }
    });
}

I guess you could write a utility function but surly there is a better way to do this? It seems too longwinded.

DigitalJohn
  • 281
  • 3
  • 12

2 Answers2

0

This looks like typical mysql/db work actually.

You may want to structure this differently actually:

this.model = MyModel.find({id:id});

try {
    this.doSomething();
} catch (e) {
    if (e instanceof SomeSpecificException) {
        var fetchPromise = this.model.fetch();
        fetchPromise.done(
            this.doSomething.bind(this)
        );
    }
}

What's happening here?

Try/Catch is a great way to notice something is not found or not existent. If you catch an error then you can fetch. Fetch should return a future/promise (if it doesn't write a shim that fixes up its prototype). When the promise resolves (comes back done) it'll call doSomething whose scope will be bound to this. That let's you remove self.

How to shim?

It'd be something like:

var Deferred = require('simply-deferred');

Backbone.Model.prototype.fetch = function(options) {
   var dfd = Deferred();

   Backbone.Model.prototype.fetch.call(
       this, 
       _.extend({ success: dfd.resolve.bind(this) }, options)
   );

   return dfd.promise;
}

The only part I'm not sure about is which function to use: Backbone.Model.prototype.fetch might point to the original Backbone fetch. You essentially want to call the Backbone-Relational fetch method pass in your options and scope. Then have the success option to resolve your promise.

Why isn't this built in? Well someone in node land decided promises weren't the default way to go thus leaving you in call back hell.

Parris
  • 17,833
  • 17
  • 90
  • 133
  • 1
    Using a try/catch for a normal condition is really bad practice. Exceptions should be thrown for exceptional conditions not used for normal program flow in place of an if/else. – jax Feb 05 '14 at 06:45
  • @jax no, try/catch is not bad! I don't know what you read that made you think that. – Parris Feb 05 '14 at 11:07
  • 1
    I never said try/catch is bad. A try/catch should not be used as part of a normal program flow though. The reason it is called an 'Exception' is because it is used for Exceptional circumstances, not normal ones. – jax Feb 05 '14 at 11:36
  • 1
    what you suggest is not wrong but it is not best practice for any language, http://stackoverflow.com/questions/8986958/javascript-exceptions-best-practices – jax Feb 08 '14 at 02:08
  • @jax there is a answer with equal rating right below that, that contradicts your point and the main answer. try/catch is fine pattern. it's taught in schools. It is defensive and lets you catch all sorts of errors and doesn't clutter your code with type checking constantly. – Parris Feb 08 '14 at 03:11
  • I will however agree it is easily abused, and in JS it is harder than normal to account for that (changed answer because I've been in python land all week). – Parris Feb 08 '14 at 03:46
0

How about this, the side effect is that the found object will get updated to the one on the server and you will do a server request regardless. It kind of defeats the purpose of caching.

this.model = MyModel.findOrCreate({id:id}).fetch({
    success: function(){
        self.doSomething();
    }
});
jax
  • 37,735
  • 57
  • 182
  • 278