How to catch an error on a Request, then open a modal, then retry when modal closes with RxJS

前端 未结 3 787
盖世英雄少女心
盖世英雄少女心 2021-02-04 14:12

I want to make a call to a server that can return an authorization fail (401) with Angular2\'s HTTP class.

The flow of the request should look like that:

  • T
相关标签:
3条回答
  • 2021-02-04 14:31

    I think that you need to return something an observable even in the case of the 401 error:

    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());
        }
    }
    

    See this article for more details: https://jaxenter.com/reactive-programming-http-and-angular-2-124560.html.

    Edit

    The problem is that the second parameter of the catch callback isn't the source observable. This source observable corresponds to the value of its source property:

    return ob.source.retryWhen((errors) => closedSubject);
    

    See the working plunkr: https://plnkr.co/edit/eb2UdF9PSMhf4Dau2hqe?p=preview.

    0 讨论(0)
  • 2021-02-04 14:37

    I guess retryWhen operator should help.

    0 讨论(0)
  • I believe the solution has changed a little, since in the news versions of Angular we must use the pipe() method. So I decided to use a custom operator solution. One good thing is the handleError() method could be exported as a global function and then be used in more than one service.

    See this solution for more details: https://blog.angularindepth.com/retry-failed-http-requests-in-angular-f5959d486294

    export class MyService {
    // ...
    public getSomething(): Observable<Response> {
        return this.http.get(url, options).pipe(this.handleError('Maybe your a custom message here'));
    }
    
    private handleError(errorMessage: string) {
        return (source: Observable<any>) => source.pipe(
            retryWhen(errors => errors.pipe(
                mergeMap((errorResponse: HttpErrorResponse) => {
                    console.error(errorMessage);
                    if (errorResponse.status === 401) {
                        const closedSubject = new Subject();
                        this.modalService.open(new ModalConfig({
                            content: LoginModalComponent,
                            close: () => {
                                closedSubject.next();
                            }
                        }));
                        return closedSubject;
                    }
                    return throwError(errorResponse);
                })
            ))
        );
    }
    

    }

    0 讨论(0)
提交回复
热议问题