Jea*_*erc 8 javascript rxjs typescript rxjs5 angular
我想调用可以使用Angular2的HTTP类返回授权失败(401)的服务器.
请求的流程应如下所示:
这就是我现在所拥有的:
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
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());
}
}
Run Code Online (Sandbox Code Playgroud)
可悲的是,它仍然无效.retryWhen立即执行,不等待closedSubject.next()被调用.因此它开始一个无限循环,垃圾邮件原始的Observable(getSomething()函数).
更新2
我创建了一个plunker来演示无限循环:
https://plnkr.co/edit/8SzmZlRHvi00OIdA7Bga
警告:运行plunker会使用字符串'test'向控制台发送垃圾邮件
更新3
按照Thierry的正确答案,我试图找到一种不使用源字段的方法,因为它受到保护.在询问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());
}
});
}
Run Code Online (Sandbox Code Playgroud)
我避免使用.catch,所以我不必使用源字段.
我认为即使在401错误的情况下你也需要返回一个可观察的东西:
public 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();
}));
return ob.retryWhen(() => closedSubject);
}
else {
return Observable.throw(res.json());
}
}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅此文章:https://jaxenter.com/reactive-programming-http-and-angular-2-124560.html.
编辑
问题是catch回调的第二个参数不是源可观察的.此source observable对应于其source属性的值:
return ob.source.retryWhen((errors) => closedSubject);
Run Code Online (Sandbox Code Playgroud)
请参阅work plunkr:https://plnkr.co/edit/eb2UdF9PSMhf4Dau2hqe ? p = preview .