backbone.js - Catching Backbone sync errors -
i needed catch possible login page in responses server, have overridden backbone.sync globally can check errors before passing them on.
backbone.originalsync = backbone.sync; backbone.sync = function (method, model, options) { var originalsuccess, originalerror; console.log("sync override..."); // remember original success can call if user logs in originalsuccess = options.success; // proxy error callback first check if login page originalerror = options.error; options.error = function (model, xhr, options) { if (xhr.status === 200 && xhr.responsetext === "") { // parse error 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 new window relogon.html trigger new login window.showmodaldialog("../relogon.html"); } else { // normal error, pass along if (originalerror) { originalerror(model, xhr, options); } } } }; // call original sync backbone.originalsync(method, model, options); };
this broke miserably when going 0.9.9 1.0. looks original backbone.sync wraps error handlers differently, causing error handler called first, jquery xhr signature. had change signature of error handler this:
options.error = function (xhr, statustxt, thrown) {
ok works, feeling doing wrong.
is there better way this?
i tried jquery promises need able switch error state success (when calling originalsuccess), did not seem work promises.
you can build own jquery deferred object alter default backbone.sync
behavior
backbone.sync = function (method, model, opts) { var xhr, dfd; dfd = $.deferred(); // opts.success , opts.error resolved against deferred object // instead of jqxhr object if (opts) dfd.then(opts.success, opts.error); xhr = backbone.originalsync(method, model, _.omit(opts, 'success', 'error')); // success : forward deferred xhr.done(dfd.resolve); // failure : resolve or reject deferred according 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 promise add callbacks if necessary return dfd.promise(); };
the promise reflects end state choose.
http://jsfiddle.net/asmyq/4/ fail demo, http://jsfiddle.net/asmyq/5/ success.
and if may
- you should not tie tightly
backbone.sync
login handling. use events, backbone orjquery.ajaxerror
@andrey suggested - your server response should indicate authorization failure, 401 status
- don't forget return deferred promise/jqxhr object when override sync, might come in handy down line
Comments
Post a Comment