0

I'm calling an endpoint which needs an authentication on the server.

/users/:userId/my/endpoint => getData(): Observable<any>

The server responds with an error, if the authentication is expired. Then i'm able to refresh this authentication with a client secret i'm sending by POST

/refresh/me => refreshAuth(): Observable<any>

After that, i'll send the first request again and get a successful response (happy case).

How can i achieve this with a single Observable? I know, there is for example catchError and retry.

getData()
  .pipe(
    catchError(e => {
      if (error.code === 1224) {
        return refreshAuth();
      }

      return throwError(error);
    }),
    retry(1)
  ).subscribe();

But this would retry every error case, right? How can i retry the whole chain once on the specific auth expired case?

schaenk
  • 633
  • 1
  • 6
  • 17
  • Look into `retryWhen` that way you can inspect the error and only emit for a retry if it meets your criteria – Mrk Sef Dec 14 '20 at 17:55

1 Answers1

1

This is how it might be implemented:

getData()
  .pipe(
    retryWhen(error => error.pipe(
      exhaustMap(e => (e.code == 1224) ? refreshAuth() : throwError(e))),
      take(1)
    )
  )
  .subscribe();
Rafi Henig
  • 5,950
  • 2
  • 16
  • 36
  • This helped a lot already, thank you. But `getData()` is now called in an infinity loop if `refreshAuth()` fails. How can i make sure, the whole chain is repeated only once? – schaenk Dec 14 '20 at 18:39
  • 1
    `exhaustMap()` for the win, thank you! I was able to solve the issue as well with `concatMap` and `iif` with some help from here https://stackoverflow.com/questions/44911251/how-to-create-an-rxjs-retrywhen-with-delay-and-limit-on-tries, but your solution is much cleaner! – schaenk Dec 14 '20 at 19:08
  • One strange thing is left... The API call behind `getData()` get's cancelled on retry. Maybe something wrong with my implementation, i'm going to check that a bit deeper. – schaenk Dec 14 '20 at 19:25
  • you mean after the first retry? this is the expected behavior – Rafi Henig Dec 14 '20 at 19:36
  • Yes, on the first retry. getData() => refreshAuth() => getData(). The second getData() got canceled. So i need to use take(2) – schaenk Dec 14 '20 at 19:43