How to call ".done" after the ajax call in Backbone fetch calls

347 views Asked by At

Instead of throwing an error, the RESTful API that I call returns 200 success with a "fault" object as part of the return data when there's an error server side. I can't change the API. To handle this (without Backbone) all ajax calls are wrapped in a class that calls ".done" after the ajax call to handle display of any "fault" that may be included in the response. Also, some callers need to be able to specify settings that indicate where the fault should be displayed, while others rely on the default location.

I want to change the code to use Backbone's sync functionality to save and retrieve my models and collections, but I'm not sure how to inject the desired settings values and .done function. I could override the prototype sync method and change it to call our custom ajax method, but it's a pretty involved function and I'm rather afraid I'd break something. I would much rather find some lighter way to call ".done" on the result of the ajax call, but I'm having difficulty figuring out how.

I see how to inject an additional error handler or success handler by overriding Backbone.Model.prototype.fetch and Backbone.Collection.prototype.fetch, per this post - How to add a default error handler to all Backbone models?. However, that doesn't give me direct access to the actual ajax call return so I don't have anything to call ".done" on, plus "fetch" only covers "get" ajax calls and I need to handle faults for all Backbone ajax calls.

Anyone have an idea how to handle this?

Thanks much!

1

There are 1 answers

0
user756366 On BEST ANSWER

I decided to override Backbone.ajax.

I found that any properties I set when calling fetch (I assume this will also work for save and destroy, but haven't tested that yet) are passed through by the framework to this method, so they are available to me there as needed. I'm not thrilled about how I'm making assumptions about Backbone's implementation there (i.e. assume the arguments will be passed to Backbone.ajax in a particular format), but this still seemed like the cleanest way.

Here's some of my code, so you can see how I'm reading the errorHandlingSettings argument. Note that the arguments are NOT passed into Backbone.ajax directly - they are stored by Backbone and then referenced there:

Backbone.ajax = function() {
    var currentArguments = {};
    if(typeof(arguments.callee) != 'undefined' 
        && typeof(arguments.callee.arguments) != 'undefined')
         currentArguments = arguments.callee.arguments[0];
   var errorHandlingSettings = {};
   if(typeof(currentArguments.errorHandlingSettings) != 'undefined')
      errorHandlingSettings = currentArguments.errorHandlingSettings;
      ... etc. - store the "successIfNoFaults" variable.
   var handleFaults = function(data){
      ... etc. (custom code using the errorHandlingSettings and successIfNoFaults variables) ...
   };

   return Backbone.$.ajax.apply(Backbone.$, arguments).done(handleFaults);
};

And here's how I'm passing the errorHandlingSettings argument (inside my view's initialize method):

this.reservationHold.fetch({errorHandlingSettings: {errorPlace:"1",errorPosition:"errorDiv"}, successIfNoFaults:function(){that.render();}});

Note that I also am passing another custom argument, "successIfNoFaults", so that I can avoid calling the "success" callback if a 200 response WITH a fault comes back.