2017-06-25 65 views
0

我正在開發一個Angular webapp,它使用API​​來獲取一些數據。 要獲得這些數據,我必須發送一個智威湯遜。 我創建,爲了調用一個PHP文件,以獲得令牌服務:如何在AngularJS中刷新過期的jwt令牌

(function() { 
'use strict'; 

angular 
.module('MyApp') 
.factory('TokenService', Service); 

function Service($http, $localStorage) { 

    var service = {}; 

    service.getToken = getToken; 

    return service; 

    function getToken() { 
     return $http.post('gettoken.php'); 
    } 
}})(); 

而我做的是在.RUN塊我把它和存儲接收的令牌:

function run($rootScope, $http, $location, $localStorage, TokenService) { 
    TokenService.getToken().then(function(response) { 
     $localStorage.token = response.data.token; 
    }); 
    console.log('token: ' + $localStorage.token); 
    $http.defaults.headers.common.Authorization = 'Bearer ' + $localStorage.token; 
}})(); 

每過幾分鐘,令牌就會過期,因此我必須請求另一個令牌,以便用戶可以繼續與API進行交互。

爲了解決這個問題,我的第一個方法是使用.config塊攔截401錯誤(令牌過期)並要求另一個令牌,但這是不可能的,因爲據我所知,不可能注入服務的.config塊:

function config2($httpProvider) { 
    $httpProvider.interceptors.push(function ($q, $rootScope) { 
     return { 
      'response': function (response) { 
      //Will only be called for HTTP up to 300 
      console.log(response); 
      return response; 
     }, 
     'responseError': function (rejection) { 
      if(rejection.status === 401) { 
       var deferred = $q.defer(); 
       TokenService.getToken(function() { 
        retryHttpRequest(response.config, deferred); 
       }); 
       return deferred.promise; 
      } else { 
       return response; 
      } 
      function retryHttpRequest(config, deferred){ 
       function successCallback(response){ 
       deferred.resolve(response); 
       } 
       function errorCallback(response){ 
       deferred.reject(response); 
       } 
       var $http = $injector.get('$http'); 
       $http(config).then(successCallback, errorCallback); 
      } 
     } 
    }; 
}); 
} 

事實上,當我執行的web應用程序,它說,TokenService沒有定義,如果我注入TokenService,顯然它創建了一個圓圈扶養:

angular.js:66 Uncaught Error: [$injector:cdep] Circular dependency found: $http <- TokenService <- $http <- $templateRequest <- $route 
http://errors.angularjs.org/1.6.4/$injector/cdep?p0=%24http%20%3C-%20TokenService%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24route 
    at angular.js:66 
    at getService (angular.js:4936) 
    at injectionArgs (angular.js:4969) 
    at Object.invoke (angular.js:4995) 
    at Object.enforcedReturnValue [as $get] (angular.js:4836) 
    at Object.invoke (angular.js:5003) 
    at angular.js:4795 
    at getService (angular.js:4944) 
    at injectionArgs (angular.js:4969) 
    at Object.invoke (angular.js:4995) 

這是一個非常愚蠢的情況,但我花了整整一天試圖fi尋找最佳解決方案。 一旦攔截器檢測到401 responseError,我試圖簡單地重新加載頁面,但這不是最佳的,因爲用戶看到網絡刷新,並且他丟失了爲請求插入的所有數據。

如果有的話,你不得不處理這類問題,可以爲了解決它共享任何方式這將是巨大的。

回答

1

這可能是因爲$http服務取決於您的攔截器,您的TokenService取決於$http服務,而您的攔截器取決於TokenService。這會導致循環依賴。

看來你已經在使用$injector來即時注入$ http-service,所以要解決你的循環依賴問題,用同樣的方法注入你的TokenService可能會解決你的問題。

var TokenService = $injector.get('TokenService'); 

我之前在同樣的問題,迷迷糊糊的,所以如果它的任何幫助,您可以check my solution on GitHub

+0

非常感謝您的幫助。 我應用了你說的。現在的問題是當我在ResponseError中調用getToken時:它返回新的令牌,但它不適用於當前的401請求,所以我收到新的令牌,但對API的請求仍然失敗。 我正在閱讀你的解決方案在GitHub上,我希望我可以用該代碼解決它。 非常感謝! – Hmorv

+1

我終於用你的工廠作爲例子調整了我的代碼。它的作品相當不錯!謝謝! – Hmorv