I needed to catch a possible login page for all server responses, so I redefined Backbone.sync globally, so I can check all the errors before passing them.
Backbone.originalSync = Backbone.sync; Backbone.sync = function (method, model, options) { var originalSuccess, originalError; console.log("sync override..."); // remember original success so we can call it if user logs in successfully originalSuccess = options.success; // proxy the error callback to first check if we get a login page back originalError = options.error; options.error = function (model, xhr, options) { if (xhr.status === 200 && xhr.responseText === "") { // parse error from empty response (jq1.9 invalid json, ok) originalSuccess(model, xhr, options); } else { console.log("Sync error " + statusTxt + ", " + thrown.message); if (xhr.status === 200 || xhr.status === 302 || xhr.status === 0) { // login page returned instead of json... // open a new window with relogon.html to trigger a new login window.showModalDialog("../relogon.html"); } else { // normal error, pass along if (originalError) { originalError(model, xhr, options); } } } }; // call the original sync Backbone.originalSync(method, model, options); };
This happened with an error when switching from 0.9.9 to 1.0. It looks like the original Backbone.sync handles error handlers differently, invoking the first call to the error handler, with a jquery xhr signature. I had to change the signature of the error handler to this:
options.error = function (xhr, statusTxt, thrown) {
Ok, now it works, but I feel like I'm doing something wrong.
Is there a better way to do this?
I tried with jquery promises, but I needed to switch from the error state to success (when calling originalSuccess), which did not seem to work with promises.