byC*_*der 5 observable rxjs restangular angular
在我的角度4应用程序中,我正在使用ngx-restangular来处理所有服务器调用.它返回可观察的结果,并且该模块具有处理错误的钩子(如401等).
但是从文档中,我可以处理403(401)所以:
RestangularProvider.addErrorInterceptor((response, subject, responseHandler) => {
if (response.status === 403) {
refreshAccesstoken()
.switchMap(refreshAccesstokenResponse => {
//If you want to change request or make with it some actions and give the request to the repeatRequest func.
//Or you can live it empty and request will be the same.
// update Authorization header
response.request.headers.set('Authorization', 'Bearer ' + refreshAccesstokenResponse)
return response.repeatRequest(response.request);
})
.subscribe(
res => responseHandler(res),
err => subject.error(err)
);
return false; // error handled
}
return true; // error not handled
});
Run Code Online (Sandbox Code Playgroud)
这对于一个已经破坏了403错误的请求很有用.如何使用rxJs堆叠此调用?例如,现在,我有3个请求,有403个,每个这个破坏的请求我刷新令牌 - 这不太好,我必须更新我的令牌,然后重复我所有破碎的请求.我怎样才能使用Observables来实现这个目标?
角度1很容易:
Restangular.setErrorInterceptor(function (response, deferred, responseHandler) {
if (response.status == 403) {
// send only one request if multiple errors exist
if (!refreshingIsInProgress) {
refreshingIsInProgress = AppApi.refreshAccessToken(); // Returns promise
}
$q.when(refreshingIsInProgress, function () {
refreshingIsInProgress = null;
setHeaders(response.config.headers);
// repeat request with error
$http(response.config).then(responseHandler, deferred);
}, function () {
refreshingIsInProgress = null;
$state.go('auth');
});
return false; // stop the promise chain
}
return true;
});
Run Code Online (Sandbox Code Playgroud)
一切都像魅力一样.但我是rxJs和angular 4的新手,我不知道如何用可观察和角度4来实现这个.也许有人有想法?
UPD!这是我的refreshAccesstoken方法
const refreshAccesstoken = function () {
const refreshToken = http.post(environment.apiURL + `/token/refresh`,
{refreshToken: 'someToken'});
return refreshToken;
};
Run Code Online (Sandbox Code Playgroud)
我看到使用 ngx-restangular 执行此操作的一种方法是使用共享运算符。这样您就不必实现复杂的排队逻辑。这个想法是,如果你有 3 个请求,所有请求都带有 403 响应,它们都会命中你的拦截器并调用你的可观察对象。如果您共享该可观察量,则对于 3 个带有损坏令牌的请求,您将只有一个令牌请求。
您只需在代码中使用共享运算符,如下所示:
refreshAccesstoken()
.share()
.switchMap(refreshAccesstokenResponse => {
//If you want to change request or make with it some actions and give the request to the repeatRequest func.
//Or you can live it empty and request will be the same.
// update Authorization header
response.request.headers.set('Authorization', 'Bearer ' + refreshAccesstokenResponse)
return response.repeatRequest(response.request);
})
.subscribe(
res => responseHandler(res),
err => subject.error(err)
);
Run Code Online (Sandbox Code Playgroud)
我还没有检查代码是否确实有效,但我之前曾在相同的用例中使用过这种方法,但我使用的是 Angular HTTP 服务,而不是拦截器。
编辑更改刷新访问令牌:
您需要将您的refreshAccessToken方法包装在延迟的Observable中并共享它。这样你每次都会重用相同的可观察值。
在构造函数中:
this.source = Observable.defer(() => {
return this.refreshAccesstoken();
}).share();
Run Code Online (Sandbox Code Playgroud)
创建另一个将调用该可观察量的方法:
refreshToken(): Observable<any> {
return this.source
.do((data) => {
this.resolved(data);
}, error => {
this.resolved(error);
});
}
Run Code Online (Sandbox Code Playgroud)
编辑2
我创建了一个git 存储库,该存储库使用 angular2 和 restangular。场景如下:
如果我删除共享运算符,我将得到以下日志:
这意味着每次都会创建可观察对象。
为了使其工作,在 RestangularConfigFactory 中声明和创建源非常重要。它本质上将成为一个单例对象,这就是共享操作符能够工作的原因。
笔记:
我为这个项目创建了一个本地托管的简单 Web API,只是因为它对我来说更快。
EDIT3:更新以包含刷新令牌的代码:
refreshAccesstoken()
.share()
.switchMap(refreshAccesstokenResponse => {
//If you want to change request or make with it some actions and give the request to the repeatRequest func.
//Or you can live it empty and request will be the same.
// update Authorization header
response.request.headers.set('Authorization', 'Bearer ' + refreshAccesstokenResponse)
return response.repeatRequest(response.request);
})
.subscribe(
res => responseHandler(res),
err => subject.error(err)
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
964 次 |
| 最近记录: |