Angular2 http重试逻辑 [英] Angular2 http retry logic

查看:644
本文介绍了Angular2 http重试逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于令牌的身份验证机制的API。成功登录后,我在浏览器的本地存储中存储了两个令牌 - 访问和刷新令牌。
访问令牌包含在服务器端授权用户所需的所有必要信息,并且它具有到期日期。
当访问令牌过期时,客户端可以使用刷新令牌请求新的访问令牌,并且在响应中它将获得一对新令牌。

I have an API with token based authentication mechanism. After successful signin I store two tokens in the browser's local storage - access and refresh token. The access token contains all necessary information required to authorize a user on the server side and it has expiration date. When the access token is expired the client could request a new access token using refresh token and in the response it will get a pair of new tokens.

In angular 1.x实现非常简单明了。例如,我们可以使用拦截器:

In angular 1.x the implementation is pretty simple and straightforward. For instance we could use interceptors:

httpInterceptor.$inject = ['$httpProvider'];
function httpInterceptor($httpProvider) {
  $httpProvider.interceptors.push(handleStaleAccessToken);

  handleStaleAccessToken.$inject = ['$q', '$injector', 'session'];
  function handleStaleAccessToken($q, $injector, session) {

    function logoutAndRedirect() {
      var authenticationRedirect = $injector.get('authenticationRedirect');
      session.destroy();
      authenticationRedirect.toLoginPage();
    }

    return {
      responseError: function(rejection) {
        // Do nothing for non 403 errors
        if (rejection.status !== 403) {
          return $q.reject(rejection);
        }

        var errorCode = rejection.data.error && rejection.data.error.code;
        if (errorCode === 'access_token_expired') {
          var $http = $injector.get('$http');

          // Refresh token
          var params = { refreshToken: session.getRefreshToken() };
          return $http.post('/api/auth/refresh', params).then(function(response) {
            session.setTokens(response.data);
            // Re try failed http request
            return $http(rejection.config);
          }).catch(function(error) {
            logoutAndRedirect();
            return $q.reject(error);
          });
        } else {
          logoutAndRedirect();
        }

        return $q.reject(rejection);
      }
    };
  }
}

但是如何在角度2 / rxjs中实现类似的逻辑app?

But how to implement similar logic in angular 2 / rxjs app?

推荐答案

这可以通过扩展 Http 类和利用可观察的运算符,如 flatMap

This can be done transparently in Angular2 by extending the Http class and leveraging observable operators like flatMap.

以下是一些示例代码:

if (hasTokenExpired()) {
  return this.authService
             .refreshAuthenticationObservable()
             .flatMap((authenticationResult:AuthenticationResult) => {
                if (authenticationResult.IsAuthenticated == true) {
                     this.authService.setAuthorizationHeader(request.headers);
                  return this.http.request(url, request);
                }
                return Observable.throw(initialError);
    });
}

此代码必须集成到<$ c $的自定义子类中c> Http 一:

一种方法可能是扩展HTTP对象以拦截错误:

An approach could be to extend the HTTP object to intercept errors:

@Injectable()
export class CustomHttp extends Http {
  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    console.log('request...');
    return super.request(url, options).catch(res => {
      // do something
    });        
  }

  get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    console.log('get...');
    return super.get(url, options).catch(res => {
      // do something
    });
  }
}

并按以下说明注册:

bootstrap(AppComponent, [HTTP_PROVIDERS,
    new Provider(Http, {
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
      deps: [XHRBackend, RequestOptions]
  })
]);

有关详细信息,请查看以下问题:

For more details have a look at these questions:

  • Handling refresh tokens using rxjs
  • Angular 2 - How to get Observable.throw globally

这篇关于Angular2 http重试逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆