Handling non-200 status codes in Backbone
Many RESTful APIs return non-200 status codes that should be considered a success
- e.g. a 201 CREATED
. However, Backbone uses the jQuery ajax
method and this will treat anything that isn't a 200
code as an error.
The jQuery ajax
method does have a statusCode
property which lets you setup a switch statement of responses depending on the returned status code. However, even if you set this to call your success
callback on a non-200 code the error
callback will still be called - which can cause problems in many instances.
However, using a similar method to that discussed in Add a root URL to all Backbone API request we can get around this problem:
define(function () {
'use strict';
/*
* Store a version of Backbone.sync to call
* with modified options
*/
var backboneSync = Backbone.sync,
/**
* New error is a currying function. You pass in a method,
* success function, and error function and it returns a
* new error function that will call the success function if
* a 'sucess code' corresponds to the method.
*/
newError = function (method, success, error) {
// Each method can have its own specific success code
var successCodes = {
create: 201
};
// Return the original error function if no matching 'success code'
if (!successCodes[method]) {
return error;
}
return function (jqXHR, textStatus, errorThrown) {
// If the response is a success code
var wasSuccessful = jqXHR.status === successCodes[method],
response;
// If the status is a 'success code' run the success function
if (wasSuccessful && _.isFunction(success) ) {
// Set the response if there is one
response = jqXHR.responseJSON ? jqXHR.responseJSON : {};
// Call the success function
success(response, textStatus, jqXHR);
// Otherwise run the error as usual
} else if (_.isFunction(error)) {
// Call the original error function
error(jqXHR, textStatus, errorThrown);
}
};
};
// Override Backbone.sync
Backbone.sync = function (method, model, options) {
// Set options to error to the new error function
options.error = newError(method, success, error);
// Call the stored original Backbone.sync method with the new settings
backboneSync(method, model, options);
};
});
This new Backbone.sync
sets the error
callback to a new function which first checks the return status code and calls the success
callback if it should be counted as successful. Otherwise it behaves as it would have originally. We can now pass in our usual error
and success
callbacks and not worry about status code handling.