【问题标题】:Interceptors for managing restricted pages in AngularJS在 AngularJS 中管理受限页面的拦截器
【发布时间】:2014-07-25 12:44:51
【问题描述】:

几天前我刚开始使用 AngularJS,我的拦截器遇到了问题,该拦截器从服务器响应中拦截 401 状态。

当返回 401 并在该事件上触发重定向时,它会广播“loginRequired”类型的消息。

问题是,如果我在未登录的情况下尝试访问受限页面,我会在重定向到登录页面之前看到页面闪烁片刻。我仍然是异步东西、承诺等方面的初学者。有人能指出我做错了什么吗?

这是我的拦截器。如您所见,它非常简单,但我将其精简以解释我的观点,并且在进一步开发之前尝试理解事物。

拦截器

var services = angular.module('services', []);

services.factory('myInterceptor', ['$q', '$rootScope',
  function($q,$rootScope) {

    var myInterceptor = {

      'responseError': function(rejection) {
        $rootScope.$broadcast('event:loginRequired');
        return $q.reject(rejection);
      }
    };

    return myInterceptor;
  }
]);

我的拦截器的注入

myApp.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push('myInterceptor');
}]);

受限页面的路由

.when('/restrictedPage', {
  templateUrl: 'partials/restrictedPage.html',
  controller: 'RestrictedPageController'
}).

受限页面控制器

controllers.controller('RestrictedPageController', function($scope) {

  //Some times the alert pops up, sometimes not.
  alert("Damn it I shouldn't be there");

});

$rootScope 事件观察器

$rootScope.$on('event:loginRequired', function() {

  //Only redirect if we aren't on free access page
  if ($location.path() == "/freeAccess")
    return;

  //else go to the login page
  $location.path('/home').replace();

});

我的问题显然在于我处理拦截器和 $q 的方式。我在github 上找到了另一种创建拦截器的方法,但这不是官方文档使用的方式,所以我认为这可能是旧方法,而且在我看来不如将它放在工厂中那么干净。他只是在他的模块的配置函数中定义了路由之后才放了这段代码。但是这段代码有效,我没有得到页面闪存。

我在 Github 上找到的另一种方式

var interceptor = ['$rootScope', '$q', '$log',
  function(scope, $q, $log) {

    function success(response) {
      return response;
    }

    function error(response) {
      var status = response.status;

      if (status == 401) {
        var deferred = $q.defer();
        var req = {
          config: response.config,
          deferred: deferred
        };
        scope.$broadcast('event:loginRequired');
        return deferred.promise;
      }
      // otherwise
      return $q.reject(response);

    }

    return function(promise) {
      return promise.then(success, error);
    };

  }
];
$httpProvider.responseInterceptors.push(interceptor);

但我的目标不仅仅是“让它发挥作用”,而且我讨厌“如果它没有坏就不要修复它”的口头禅。我想了解我的代码有什么问题。谢谢!

【问题讨论】:

    标签: javascript angularjs angular-http angular-promise angular-http-interceptors


    【解决方案1】:

    不要从拦截器中广播“event:loginRequired”,而是尝试在拦截器中执行位置路径更改。广播会增加接收 401 和更改位置之间的延迟,并且可能是屏幕“闪烁”的原因。

    services.factory('myInterceptor', ['$q', '$rootScope', '$location',
      function($q, $rootScope, $location) {
    
        var myInterceptor = {
    
          'responseError': function(rejection) {
             if (response.status === 401 && $location.path() !== '/freeAccess') {
               //else go to the login page
               $location.path('/home').replace();
             }
             // otherwise
             return $q.reject(response);
          }
        };
    
        return myInterceptor;
      }
    ]);
    

    您还可以在您的应用模块首次运行时执行 HTTP 请求,以立即确定用户是否已获得授权:

    myApp.config(['$httpProvider', function($httpProvider) {
      $httpProvider.interceptors.push('myInterceptor');
    }])
    .run(function($http) {
      //if this returns 401, your interceptor will be triggered
      $http.get('some-endpoint-to-determine-auth'); 
    });
    

    【讨论】:

    • 非常感谢!这完美!哇,我不敢相信我没有考虑在我的拦截器中注入 $location。
    猜你喜欢
    • 1970-01-01
    • 2018-01-20
    • 2015-11-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 2015-04-12
    • 2013-07-01
    • 1970-01-01
    相关资源
    最近更新 更多