backbone.js - Is there a way to intercept Marionette routes and model fetches? -


is there way intercept marionettejs operations such routing , model fetching?

a parallel $httpinterceptor in angularjs (https://stackoverflow.com/a/11957760/41887)

the use case i'm interested in handling user authentication, redirect login page/route should there no current user authentication. while handle in each controller, i'd prefer have single general mechanism globally applied.

update:

for fetching interception i've seen 1 suggestion follows:

authenticationmodule.addinitializer ->   # tell jquery watch 401 or 403 errors , handle them appropriately   $.ajaxsetup {     statuscode: {       401: -> window.location.replace('#login')       403: -> window.location.replace('#denied')     }   }   

but doesn't work if want validate against in addition http response code (i.e. user entity/representation in memory).

marionette.approuter extends standard backbone.router, neither of them provides interception mechanism allow prevent execution of route callback. in need of same features, came following code (_ lodash). in original backbone.router.prototype.route(), function executed on route match created. following code provides wrapper original backbone.router.prototype.route() in order replace registered route callback function execute chain of middleware functions. each of these middleware can perform additional processing before or after execution of original route callback, including preventing execution of further callback , raise exception.

backbone.routemiddlewares = (function () {    var backbone = require('backbone')     , _ = require('lodash');    /**    *  wrapper `backbone.router.prototype.route()` use route middlewares (in addition    * normal callback).    *    * @param {function} fn - wrapped function (should compatible `backbone.router.prototype.route()`).    * @param {string|regexp} route - route pattern or regexp.    * @param {string} name - name of route.    * @param {function} callback - route callback.    * @returns {backbone.router}    */   function routemiddleware(fn, route, name, callback) {     // prepare arguments original backbone.router.prototype.route() would.     if (!_.isregexp(route)) route = backbone.router.prototype._routetoregexp.apply(this, [route]);     if (_.isfunction(name)) {       callback = name;       name = '';     }     if (!callback) callback = this[name];      // execute wrapper `route` method, callback final middleware.     return fn.apply(this, [route, name, function () {       executemiddlewares.apply(this, [route, name, backbone.history.getfragment(),  array.prototype.slice.apply(arguments, [0]), callback]);     }]);    };    /**    * add route middelware.    *    * @param {routemiddleware} fn    */   routemiddleware.use = function use(fn) {     middlewares.push.apply(middlewares, _.filter(arguments, _.isfunction));   };    /**    * @callback routemiddleware    * @param {regexp} route - matched route regexp.    * @param {string} name - matched route.    * @param {string} fragment - matched url fragment.    * @param {array} args - route arguments (extracted `fragment`).    * @param {function} next - function call execute next middleware in chain.    */    /**    * @type {routemiddleware[]}    */   var middlewares = [];    /**    * execute route middlware, ending provided callback.    *    * @param {regexp} route - matched route regexp.    * @param {string} name - matched route.    * @param {string} fragment - matched url fragment.    * @param {array} args - route arguments (extracted `fragment`).    * @param {function} callback - route handler execute final middleware.    */   function executemiddlewares(route, name, fragment, args, callback) {     var index = 0;     var h = middlewares.concat(function (route, name, fragment, args, next) {       callback.apply(this, args);     });     function next(err) {       if (err) throw err;       h[index++].apply(this, [route, name, fragment, args, next.bind(this)]);     }     next.apply(this);   }  })();  backbone.router.prototype.route = _.wrap(backbone.router.prototype.route, backbone.routemiddlewares); 

using interceptors/middlewares mechanism, redirection of user login page achieved following:

backbone.routemiddlewares.use(function (route, name, fragment, args, next) {   if (app.routerequiresauthentication(name) && !app.isuserauthenticated()) {     backbone.history.navigate('login', {trigger: true});   }   else {     next();   } }); 

note: being able execute code after route callback via middlewares redundant route events on router , on backbone.history comes free middleware pattern.


Comments