Angular2 http 重试逻辑 [英] Angular2 http retry logic
问题描述
我有一个基于令牌的身份验证机制的 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.
在 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);
}
};
}
}
但是如何在 angular 2/rxjs 应用程序中实现类似的逻辑?
But how to implement similar logic in angular 2 / rxjs app?
推荐答案
这可以在 Angular2 中通过扩展 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);
});
}
这段代码必须集成到一个Http
的自定义子类中:
This code must be integrated into a custom sub class of the Http
one:
一种方法是扩展 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
});
}
}
并按如下所述进行注册:
and register it as described below:
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:
这篇关于Angular2 http 重试逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!