Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 角度http拦截器 角度http拦截器不适用于从拦截器内初始化的请求?_Angularjs_Angular Http Interceptors - Fatal编程技术网

Angularjs 角度http拦截器 角度http拦截器不适用于从拦截器内初始化的请求?

Angularjs 角度http拦截器 角度http拦截器不适用于从拦截器内初始化的请求?,angularjs,angular-http-interceptors,Angularjs,Angular Http Interceptors,在我们的代码库中,对我们的api的每个请求都有一个以/api/开头的url,我们有一个拦截器,用我们的api的实际地址更新这些请求(一方面可以很容易地在开发和生产环境之间切换)。 更新url后,如果存在访问令牌,拦截器还会添加授权标头。这一切都很完美 然而,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先要向我们的api发出请求,以获取一个新的访问令牌 因此,在拦截器的请求部分,我们调用负责刷新访问令牌的服务,然后在该方法返回的回调中,我们更新原始请求的配置: //Thi

在我们的代码库中,对我们的api的每个请求都有一个以
/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
的“最新”版本。