【发布时间】:2017-11-28 09:43:14
【问题描述】:
我正在开发一个 Angular webapp,它使用 API 来获取一些数据。 要获取该数据,我必须发送一个 JWT。 我创建了一个调用 PHP 文件以获取令牌的服务:
(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);
}
}
};
});
}
确实,当我执行webapp时,它说没有定义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)
这是一个非常愚蠢的情况,但我花了一整天的时间试图找到一个最佳解决方案。 一旦拦截器检测到 401 responseError,我尝试简单地重新加载页面,但这不是最佳选择,因为用户看到网络正在刷新并且他丢失了为请求插入的所有数据。
如果你们中的任何人不得不处理这种问题并且可以分享任何方法来解决它,那就太好了。
【问题讨论】: