Jibeee
Jibeee

Reputation: 852

Handling 401 error with refresh token and call the same function

I made researches for hours but I can't find solution to my problem. Basically, I'm trying to handle 401 Error inside an ionic project using typescript. If it happens, I need to refresh my accessToken and then recall the same function. I made a code that does the trick but the recall is made inside the component and it is a bad design. How can I recall a function which should return an Observable ?

My component :

getInfos(){

    this.userService.getInfosUser()
    .subscribe(
    response => {
         console.log('success : ' , response); // Then do some logic
    },
    error => {
        this.showErrorPage(error);
    }
  )

My provider :

getInfosUser(): Observable<Response> {

    return this.authHttp.get(this.apiUrl+'getuserinfos')
    .map((response: Response) => {
        return response;
    })
    .catch((error: any) => {

        if ( error.status === 401 || error.status === "401" ) {

            // Get and set the new accessToken
            this.authService.handleError(error)
            .then((result) => {

                // Should recall getInfosUser() the function here, how ?
            });


            return Observable.throw( new Error(error.status) );
        }
        else {
            return Observable.throw( new Error(error.status) );
        }
    })

Upvotes: 0

Views: 998

Answers (1)

Jon G St&#248;dle
Jon G St&#248;dle

Reputation: 3904

I'm assuming that this.authService.handleError() returns a promise, so we'll convert that to an observable. And if that is successful, we'll add a call to getInfoUser() to that observable.

getInfosUser(): Observable<Response> {

    return this.authHttp.get(this.apiUrl+'getuserinfos')
    .map((response: Response) => {
        return response;
    })
    .catch((error: any) => {

        if ( error.status === 401 || error.status === "401" ) {

            return Observable.fromPromise(this.authService.handleError(error)).concat(getInfosUser());
        }
        else {
            return Observable.throw( new Error(error.status) );
        }
    })
}

There is a possibility that you could end up in an infinite loop here, so you could add some simple retry logic like this:

getInfosUser(maxRetries = 2): Observable<Response> {

    return this.authHttp.get(this.apiUrl+'getuserinfos')
    .map((response: Response) => {
        return response;
    })
    .catch((error: any) => {

        if ( (error.status === 401 || error.status === "401") && maxRetries > 0 ) {

            return Observable.fromPromise(this.authService.handleError(error)).concat(getInfosUser(maxRetries - 1));
        }
        else {
            return Observable.throw( new Error(error.status) );
        }
    })
}

Upvotes: 1

Related Questions