【发布时间】:2016-08-07 21:15:00
【问题描述】:
我想使用 Angular2 的 HTTP 类调用可以返回授权失败 (401) 的服务器。
请求的流程应该是这样的:
- 用户使用 myService.getSomething().subscribe() 向服务器发出请求
- 如果服务器返回 401:打开一个模式窗口,询问用户他的凭据。
- 用户成功登录应用程序
- 模态关闭并执行回调
- 回调应该重试初始请求 (myService.getSomething().subscribe())
这是我目前拥有的:
export class MyService {
// ...
public getSomething(): Observable<Response> {
return this.http.get(url, options).catch((res: any, ob: any) => this.errorHandler(res, ob));
}
public errorHandler(res: Response, ob: Observable<any>): Observable<Response> {
if (res.status === 401) {
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close: () => { ob.retry(1); console.log("weow") } // <=close is the callback that should initiate the retry action on the initial request.
}));
}
else {
return Observable.throw(res.json());
}
}
}
doSomething() 是这样使用的:doSomething().map((r) => r.json()).subscribe((r) => ....)
更新 1
我修改了我的代码,使其看起来像 @Thierry Templier 的解决方案。
private errorHandler(res: Response, ob: Observable<any>): Observable<Response> {
if (res.status === 401) {
let closedSubject = new Subject();
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close: () => { closedSubject.next(res);} // I also tried .complete(), .next(null), .next(true), .next(false)
}));
return ob.retryWhen(() => closedSubject);
}
else {
return Observable.throw(res.json());
}
}
遗憾的是它仍然不起作用。 retryWhen 会立即执行,并且不会等待 closedSubject.next() 被调用。因此它启动了一个无限循环,向原始 Observable(getSomething() 函数)发送垃圾邮件。
更新 2
我创建了一个 plunker 来演示无限循环:
https://plnkr.co/edit/8SzmZlRHvi00OIdA7Bga
警告:运行 plunker 会向您的控制台发送字符串“test”的垃圾邮件
更新 3
按照蒂埃里的正确答案,我试图找到一种不使用源字段的方法,因为它受到保护。在询问 rxjs 的问题跟踪器以公开该字段后,一位贡献者回复了一个更好的解决方案。
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return super.get(url, options).retryWhen((errors: any) => this.errorHandler(errors));
}
private errorHandler(errors): any {
return errors.switchMap((err) => {
if (err.status === 401) {
let closedSubject = new Subject();
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close: () => { closedSubject.next(err); }
}));
return <any>closedSubject;
}
else {
return Observable.throw(err.json());
}
});
}
我避免使用 .catch,因此我不必使用源字段。
【问题讨论】:
-
现在一切正常吗?
标签: javascript typescript angular rxjs rxjs5