Angularjs 角度http拦截器 角度http拦截器不适用于从拦截器内初始化的请求?
在我们的代码库中,对我们的api的每个请求都有一个以Angularjs 角度http拦截器 角度http拦截器不适用于从拦截器内初始化的请求?,angularjs,angular-http-interceptors,Angularjs,Angular Http Interceptors,在我们的代码库中,对我们的api的每个请求都有一个以/api/开头的url,我们有一个拦截器,用我们的api的实际地址更新这些请求(一方面可以很容易地在开发和生产环境之间切换)。 更新url后,如果存在访问令牌,拦截器还会添加授权标头。这一切都很完美 然而,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先要向我们的api发出请求,以获取一个新的访问令牌 因此,在拦截器的请求部分,我们调用负责刷新访问令牌的服务,然后在该方法返回的回调中,我们更新原始请求的配置: //Thi
/api/
开头的url,我们有一个拦截器,用我们的api的实际地址更新这些请求(一方面可以很容易地在开发和生产环境之间切换)。
更新url后,如果存在访问令牌,拦截器还会添加授权标头。这一切都很完美
然而,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先要向我们的api发出请求,以获取一个新的访问令牌
因此,在拦截器的请求
部分,我们调用负责刷新访问令牌的服务,然后在该方法返回的回调中,我们更新原始请求的配置:
//This interceptor only applies to our api calls, do nothing for other requests
if(config.url.substring(0, API_PREFIX.length) !== API_PREFIX) {
return config;
}
config.url = config.url.replace(API_PREFIX, API_ENDPOINT);
// if we are authenticated, we add the authorization header already
if(AuthSessionService.isAuthenticated()) {
config.headers['Authorization'] = "Bearer " + AuthSessionService.getAccessToken();
return config;
}
// so we are not authenticated, but we still do have a refresh-token, this means, we should get a new access-token
if(AuthSessionService.hasRefreshToken()) {
var deferred = $q.defer(),
loginService = angular.injector(['MyApp']).get('LoginService');
loginService.refresh().then(function(result) {
config.headers['Authorization'] = "Bearer " + AuthSessionService.getAccessToken();
deferred.resolve(config);
}).catch(function() {
deferred.reject('Failed to refresh access token');
});
return deferred.promise;
}
//no access-token, no refresh-token, make the call without authorization headers
return config;
但是,登录服务发出的请求似乎没有应用拦截器,因此请求转到/api/login
,而不是实际的api端点
这是Angular的设计吗?当从拦截器的请求方法中发出新的http请求时,不会应用拦截器?您的代码流如下:
0)AngularJS定义$httpProvider
1) 您定义了依赖于$httpProvider
注入$http
的loginService
2) 您定义了一个依赖于loginService
的HTTP拦截器,并更改了$HTTP
的工作方式
3) 您可以定义其他注入$http
的服务
看看函数,AngularJS提供程序必须提供的$get
方法。每次您的服务将$http
作为依赖项和$http
注入时,都会调用它
现在,如果您返回到,您将看到在调用$get
时会生成一个反向interceptor
列表。它是一个局部变量,因此返回的$http
实例将能够使用它,这就是这里的答案,reversedInterceptors
是您注入的$http
的每个“实例”的不同引用
因此,在loginService
(1)中注入的$http
不同于在所有其他服务(3)中注入的$http
,区别在于它的反向interceptors
尚未包含您在步骤(2)中添加的拦截器
关于服务与供应商。
服务是建立在提供者之上的,基本上是这样做的:
function MyService() {
...
}
angular.service('MyService', MyService);
// which Angular translates to this
function MyServiceProvider() {
var myService = new MyService();
this.$get = function() {
return myService;
};
}
angular.provider('MyServiceProvider', MyServiceProvider);
而供应商是:
function MyOtherProvider() {
var someStuff = [1, 2, 3];
this.$get = function() {
var otherStuff = [5, 6, 7]; // this is how reversedInterceptors is
// initialized in `$httpProvider`
function get(url) {
// do stuff, maybe use otherStuff
}
return {
get: get
};
};
}
angular.provider('MyOtherProvider', MyOtherProvider);
Angular只实例化一次MyServiceProvider
和MyOtherProvider
,但内部发生的情况不同。您如何注入loginService
?我猜它依赖于$http
,对吗?因此,这将是一个循环依赖性问题。我猜解决方法是您问题的原因。另外,使用创建您自己的承诺的反模式,而不是使用$http
返回的承诺,我个人会使用广播,然后您可以从任何位置开始新的呼叫want@SergiuParaschivloginService是通过'angular.injector().get'检索的('LoginService')以防止循环依赖性问题。@charlietfl我正在返回LoginService的承诺(这是由$http
返回的承诺)以前,但没有结果运气。所以我尝试了这种方法,但也没有运气。哇,谢谢。但是我认为我对这些服务的理解是不完整的。我认为在任何地方注入服务都会注入相同的实例。但它不是服务:)提供者不是服务。Angular实例化了一个$get
方法Angular,然后在每次注入它时调用它并给出返回值。正如您所见,每次调用$get
时都会生成拦截器列表,因此它取决于调用它的时间。另一方面,角度服务总是返回相同的实例。谢谢。我将拦截器更改为已注入$injector
服务,并使用该服务获取loginService返回已配置拦截器的服务!是的,这就是为什么我最初说“我猜解决方法是您问题的原因。”:)注入$injector
意味着您可以在每次需要时获得$http
的“最新”版本。