0

ルーティングやモデルの取得など、MarionetteJS の操作を一般的に傍受する方法はありますか?

AngularJS の $httpInterceptor も同様です ( https://stackoverflow.com/a/11957760/41887 )

私が処理したいユースケースはユーザー認証で、現在のユーザー認証がない場合にログインページ/ルートにリダイレクトします。これを各コントローラーで具体的に処理することもできますが、グローバルに適用される単一の一般的なメカニズムを使用することをお勧めします。

アップデート:

インターセプトの取得については、次のような提案が 1 つあります。

AuthenticationModule.addInitializer ->
  # Tell jQuery to watch for any 401 or 403 errors and handle them appropriately
  $.ajaxSetup {
    statusCode: {
      401: -> window.location.replace('#login')
      403: -> window.location.replace('#denied')
    }
  }  

ただし、HTTP 応答コード (つまり、メモリ内のユーザー エンティティ/表現) に加えて何かに対して検証したい場合は、同様に機能しません。

4

2 に答える 2

1

Marionette.AppRouterは標準を拡張しますがBackbone.Router、どちらもルート コールバックの実行を防止できるインターセプト メカニズムを提供しません。同じ機能が必要なため、次のコードを思いつきました ( _is Lodash )。元のBackbone.Router.prototype.route()では、ルート マッチで実行される関数が作成されます。Backbone.Router.prototype.route()次のコードは、登録されたルート コールバックを一連のミドルウェア関数を実行する関数に置き換えるために、オリジナルのラッパーを提供します。これらの各ミドルウェアは、元のルート コールバックの実行前または実行後に追加の処理を実行できます。これには、さらなるコールバックの実行の防止や例外の発生が含まれます。

Backbone.RouteMiddlewares = (function () {

  var Backbone = require('backbone')
    , _ = require('lodash');

  /**
   * A  wrapper for `Backbone.Router.prototype.route()` that will use route middlewares (in addition to its
   * normal callback).
   *
   * @param {Function} fn - The wrapped function (should be compatible with `Backbone.Router.prototype.route()`).
   * @param {string|RegExp} route - A route pattern or regexp.
   * @param {string} name - The name of the route.
   * @param {Function} callback - The route callback.
   * @returns {Backbone.Router}
   */
  function RouteMiddleware(fn, route, name, callback) {
    // Prepare arguments as the 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 the wrapper `route` method, with the callback as 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 a route middelware.
   *
   * @param {RouteMiddleware} fn
   */
  RouteMiddleware.use = function use(fn) {
    middlewares.push.apply(middlewares, _.filter(arguments, _.isFunction));
  };

  /**
   * @callback RouteMiddleware
   * @param {RegExp} route - The matched route regexp.
   * @param {string} name - The matched route.
   * @param {string} fragment - The matched URL fragment.
   * @param {Array} args - The route arguments (extracted from `fragment`).
   * @param {Function} next - The function to call to execute the next middleware in the chain.
   */

  /**
   * @type {RouteMiddleware[]}
   */
  var middlewares = [];

  /**
   * Execute the route middlware, ending with the provided callback.
   *
   * @param {RegExp} route - The matched route regexp.
   * @param {string} name - The matched route.
   * @param {string} fragment - The matched URL fragment.
   * @param {Array} args - The route arguments (extracted from `fragment`).
   * @param {Function} callback - The route handler to execute as 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);

このインターセプター/ミドルウェア メカニズムを使用すると、次の方法でユーザーをログイン ページにリダイレクトできます。

Backbone.RouteMiddlewares.use(function (route, name, fragment, args, next) {
  if (App.routeRequiresAuthentication(name) && !App.isUserAuthenticated()) {
    Backbone.history.navigate('login', {trigger: true});
  }
  else {
    next();
  }
});

注: ルート コールバックの後にミドルウェアを介してコードを実行できることはroute、ルーターとオンのイベントで冗長ですがBackbone.history、ミドルウェア パターンでは無料です。

于 2015-04-13T20:06:24.913 に答える
0

Backbone.sync を利用できます。この同期は、バックボーンがすべてのフェッチ、保存操作で呼び出す関数です。デフォルトでは、jquery ajax を使用して呼び出しを行います。サーバーとのやり取りを制御できるように、Backbone.sync 関数内の ajax 呼び出しをオーバーライドできます。ここにBackbone.Sync のドキュメントがあります

于 2013-07-15T13:48:56.817 に答える