Catching baseline errors

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.

+6
source share
2 answers

You can create your own jQuery deferred object to change the default behavior of Backbone.sync

 Backbone.sync = function (method, model, opts) { var xhr, dfd; dfd = $.Deferred(); // opts.success and opts.error are resolved against the deferred object // instead of the jqXHR object if (opts) dfd.then(opts.success, opts.error); xhr = Backbone.originalSync(method, model, _.omit(opts, 'success', 'error')); // success : forward to the deferred xhr.done(dfd.resolve); // failure : resolve or reject the deferred according to your cases xhr.fail(function() { if (xhr.status === 200 && xhr.responseText === "") { dfd.resolve.apply(xhr, arguments); } else { if (xhr.status === 200 || xhr.status === 302 || xhr.status === 0) { console.log('login'); } dfd.reject.apply(xhr, arguments); } }); // return the promise to add callbacks if necessary return dfd.promise(); }; 

The promise reflects the final state that you choose.

http://jsfiddle.net/AsMYQ/4/ to demonstrate failure, http://jsfiddle.net/AsMYQ/5/ for success.

And if I can

  • you probably shouldn't be so closely associated with Backbone.sync with your registration. Use events starting with Backbone or jQuery.ajaxError , as @Andrey suggested
  • your server’s response should indicate an authorization failure, possibly status 401
  • don’t forget to return the deferred promise object / jqXHR when you redefine synchronization, which may come in handy in a string
+8
source

All synchronization errors are passed to the error model, so you can listen to this event.

From http://backbonejs.org/#Events-catalog :

"error" (model, xhr, options) - when the model server crashes is not performed on the server.

To fix the error globally, you can use http://api.jquery.com/ajaxError/

+9
source

Source: https://habr.com/ru/post/944690/


All Articles