Wajahath
Wajahath

Reputation: 4068

How can I retry with a delay in RxJs without using the deprecated retryWhen?

I want to retry an observable chain with a delay (say, 2 seconds).

There are some similar questions answered with retryWhen. But retryWhen seems deprecated and I don't want to use it.

The following code works, without adding the delay, but how can I add delay into this chain?

of('trigger')
  .pipe(
    switchMap(() => fetchData()),
    retry(5),
    catchError(() => of(returnThisIfRetriesAreFailed))
  )
  .subscribe(console.log);

StackBlitz entry

I tried adding delay(2000), but it does not seem to be working.

Upvotes: 12

Views: 14645

Answers (3)

Adnan
Adnan

Reputation: 717

You could also add a method to the delay object key and do some other checks. I am just pasting a piece of my code so you could get the point.

// A custom method to check should retry a request or not

shouldRetry(error: HttpErrorResponse) {
    // Example for catching specific error code as well
    if (error.status === 503) {
      return timer(1000); // Adding a timer from RxJS to return observable to delay param.
    }

    throw error;
  }

// Retry operator somewhere in your code
retry({ count: 2, delay: this.shouldRetry })

Upvotes: 13

ggradnig
ggradnig

Reputation: 14199

I am not sure what you mean by

The delay and retry is applicable only if the first try fails

I couldn't find any condition in the source code that would limit the delay option to be applicable only to the first failed attempt.

So you should be able to pass as a delay either a fixed number or an Observable. For example:

of('trigger')
  .pipe(
    switchMap(() => fetchData()),
    retry({count: 5, delay: 2000}),
    catchError(() => of(returnThisIfRetriesAreFailed))
  )
  .subscribe(console.log);

If you meant you only want to delay on the first retry, then you could try something like this:

of('trigger')
  .pipe(
    switchMap(() => fetchData()),
    retry({count: 5, delay: (_, retryCount) => retryCount === 1 ? timer(2000) : of({})}),
    catchError(() => of(returnThisIfRetriesAreFailed))
  )
  .subscribe(console.log);

Upvotes: 14

Daniel Zin
Daniel Zin

Reputation: 499

Use:

of('trigger').pipe(
    switchMap(() => fetchData()),
    catchError((err, caught) => caught.pipe(
                    repeat({ count: 1, delay: 2000 }),
                    catchError(() => of(returnThisIfRetriesAreFailed))
              ))
)
.subscribe(console.log);

Upvotes: 0

Related Questions