Plastic Rabbit
Plastic Rabbit

Reputation: 2989

Global error handler for backbone.js ajax requests

Is there way to bind one error handler for ajax requests that performs by backbone.js?

My situation: I can get 401 (Unauthorized) at any time, so I need to show login popup.

Upvotes: 36

Views: 16751

Answers (4)

Henry Wilson
Henry Wilson

Reputation: 3351

You can handle this via the jQuery .ajaxSetup method. We have an identical situation (backbone app which may get a 401 error at any time) and we handle it by using jQuery's ajaxSetup in the entry point of our app:

var appView = new AppView(options);

$.ajaxSetup({
    cache: false,
    statusCode: {
        401: function () {
            appView.signIn();
        }
    }
});

appView.render();

Backbone.history.start({ root: config.rootUrl, pushState: true });

This approach gives global error handling without the need to extend the Backbone base classes.

Upvotes: 10

Julien
Julien

Reputation: 9216

Use jQuery directly for this.

$(document).ajaxError(function (e, xhr, options) {
  // do your stuff
});

You can do the same thing for CSRF in rails for exemple (using ajaxSend).

You can read more here: http://api.jquery.com/jQuery.ajax#advanced-options

Upvotes: 24

Vytautas Butkus
Vytautas Butkus

Reputation: 5535

What I found is possibly the "most right way" in Backbone:

var GeneralErrorView = Backbone.View.extend({
  events: {
    'ajaxError': 'handleAjaxError'
  },
  handleAjaxError: function (event, request, settings, thrownError) {
    //...handling goes here
  }
});

this.view = GeneralErrorView({el: document});

You can put any error handling logic without extending Models or Collections. Make use of Backbone.Events inside handler and transmit messages to other error handlers or something like that.

Upvotes: 15

Bill Eisenhauer
Bill Eisenhauer

Reputation: 6183

Backbone's sync triggers an 'error' event when errors occur. So one approach you could take is to extend Backbone's Model and Collection objects to add these add-on error checks. It would look something like this:

ErrorHandlingModel = Backbone.Model.extend({

    initialize: function(attributes, options) {
        options || (options = {});
        this.bind("error", this.defaultErrorHandler);
        this.init && this.init(attributes, options);
    },

    defaultErrorHandler: function(model, error) {
        if (error.status == 401 || error.status == 403) {
            // trigger event or route to login here.
        }
    }

});

OtherModel = ErrorHandlingModel.extend({
});

and you would do something similar for the Collection object. I haven't tested the above, but think its pretty close. Obviously, you would choose better class names. The init method just enables subclasses to get a chance to do their own initialization.

Upvotes: 25

Related Questions