AngularJS:将数据从控制器传递到app config

时间:2015-11-12 15:51:24

标签: angularjs global-variables angular-http-interceptors

我对Angular很新。我在Angular应用程序中使用令牌身份验证。我使用HTTP拦截器来检查我的后端何时返回401,而不是使用刷新令牌进行登录:

myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
  var sessionRecoverer = {
    responseError: function(response) {
      // Session has expired
      if (response.status === 401) {
        var $http = $injector.get('$http');
        var deferred = $q.defer();
        var $auth = $injector.get('$auth');

        $auth.login({
          refresh_token: ????,
          grant_type: 'refresh_token',
          event_client: 'client',
          client_id: 'id'
        });

        // When the session recovered, make the same backend call again and chain the request
        return deferred.promise.then(function() {
          return $http(response.config);
        });
      }
      return $q.reject(response);
    }
  };
  return sessionRecoverer;
}]);

现在,refresh_token来自我的登录控制器(它从api后端拉出)。所以控制器必须以某种方式将它传递给拦截器。问题是拦截器在配置块中,所以没有服务,值等 - 只有提供者。但是提供者不能注入控制器。那么有没有办法将数据从控制器传递到app.config?如果没有,是否有解决方法?注入器可以在除app.config以外的任何其他位置吗?

1 个答案:

答案 0 :(得分:1)

是的,你可以这样做:

    myapp.config(...)
    ...
    $httpProvider.interceptors.push(['$q', '$injector', function($q, $injector, TokenFactory) {
      var sessionRecoverer = {
        responseError: function(response) {
          // Session has expired
          if (response.status === 401) {
            var $http = $injector.get('$http');
            var deferred = $q.defer();
            var $auth = $injector.get('$auth');

            $auth.login({
              refresh_token: TokenFactory.getRefreshToken(),
              grant_type: 'refresh_token',
              event_client: 'client',
              client_id: 'id'
            });

            // When the session recovered, make the same backend call again and chain the request
            return deferred.promise.then(function() {
              return $http(response.config);
            });
          }
          return $q.reject(response);
        }
      };
      return sessionRecoverer;
    }]);

正如你所说,块配置只能注入提供者,但是拦截器本身就是工厂,因此你可以注入其他工厂,例如,一个名为TokenFactory的工厂,它应该提供一个返回刷新令牌的方法。需要的。

修改

如果refresh_token是来自后端的东西,并且您想在登录控制器中设置TokenFactory中的值,那么您可以执行以下操作来实现工厂和控制器:

myapp.factory('TokenFactory',function(){

  var currentRefreshToken;

  return {
    setRefreshToken: function(token){
      currentRefreshToken = token;
    },
    getRefreshToken: function(){
      return currentRefreshToken:
    }
  };
});

myapp.controller('MyLoginCtrl',function($scope,TokenFactory,$http){

  $scope.login = function(){
    $http.post('http://myapp.com/refreshtoken',$scope.credentials)
      .then(TokenFactory.setRefreshToken)
      .then(function(){ /* ... */})
      .catch(function(err){ console.error(err) })
    ;
  };

});

数据持久性

如果您想让自己的代币持续存在,可以编写一个使用LocalStorage HTML5 API的工厂并在TokenFactory中使用它:

myapp.factory('TokenFactory',function(LocalStorage){

  // load the value from localstorage (hard disk) on app starts
  var currentRefreshToken = LocalStorage.get('myapp.currentRefreshToken');

  return {
    setRefreshToken: function(token){
      currentRefreshToken = token; // save value in RAM
      LocalStorage.set('myapp.currentRefreshToken',token); // and sync the localstorage value
    },
    getRefreshToken: function(){
      return currentRefreshToken; // quick access to the value from RAM
    }
  };
});

myapp.factory('LocalStorage',function($window) {

    var localStorage = {};

    localStorage.set = function(key, value) {
        $window.localStorage[key] = value;
    };
    localStorage.get = function(key, defaultValue) {
        return $window.localStorage[key] || defaultValue;
    };
    localStorage.setObject = function(key, value) {
        $window.localStorage[key] = JSON.stringify(value);
    };
    localStorage.getObject = function(key) {
        return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? {} : JSON.parse($window.localStorage[key]);
    };
    localStorage.setArray = function(key, array){
        if (!array.length) {
            console.debug(array);
            $window.localStorage[key] = '[]';
        } else{
            this.setObject(key, array);                    
        }
    };
    localStorage.getArray = function(key){
        return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? [] : JSON.parse($window.localStorage[key]);
    };
    localStorage.exportAsFile = function(key, fileName){        
        var data = [$window.localStorage[key]] || ['{}'];
        var blob = new Blob(data,{type:'application/json;charset=utf-8'});
        $window.saveAs(blob,fileName);
    };
    return localStorage;
});