Home > OS >  Authenticate then retry with interceptor & ngrx store events
Authenticate then retry with interceptor & ngrx store events

Time:08-03

I have the following code in an interceptor:

intercept(request: HttpRequest<any>, next: HttpHandler): any {
    return next.handle(request).pipe(
      catchError(async error => {
        if (error instanceof HttpErrorResponse && (error.status === 302 || error.status === 401 || error.status === 403)) {
          this.store.dispatch(new Authenticate());
          try {
            await firstValueFrom(this.store.pipe(
              select(selectAuthCallState),
              filter(state => state === ProcessState.COMPLETED),
              take(1)
            ));
          } catch (err) {
            return throwError(async () => new Error(error.message));
          }
        }
        return next.handle(request);
      })
    );
  }
  1. When a HTTP request is getting a 401 error (for instance), it gets into the catchError block as expected.
  2. this.store.dispatch(new Authenticate()); is dispatching an authentication event, which works as expected.
  3. Then, in order to detect the authentication completion, I'm awaiting the action to finish (by awaiting the selector update) - works perfectly.
  4. I'm then trying to recall the original request (which was rejected by the lack of authentication), and nothing happens.

What am I doing wrong?

Thanks!

CodePudding user response:

I notice some bugs, Im not should that fixing them would fix your app

  • lack of async before interceptor
  • this rxjs's pipe doesn't have any retryWhen or retry (check this tutorial)

CodePudding user response:

Here's the solution I came up with. Should be switched to retry instead of deprecated retryWhen.

intercept(request: HttpRequest<any>, next: HttpHandler): any {
    return next.handle(request).pipe(
      retryWhen(errors => {
        let count = 0;
        return errors.pipe(
          takeWhile(_ =>   count <= this.RETRY_COUNT),
          concatMap(async (error) => {
            if (error instanceof HttpErrorResponse &&
              (error.status === 302 || error.status === 401 || error.status === 403)
            ) {
              this.store.dispatch(new Authenticate());
              await firstValueFrom(this.store.pipe(
                select(selectAuthCallState),
                filter(state => state === ProcessState.COMPLETED),
                take(1)));
              return of(error);
            }
            return throwError(() => new Error(error.message));
          }),
        );
      })
    );
  }
  • Related