What should the operator do?

It should retry x times with a delay of y. I came up with these explicit criteria while reviewing other approaches:

  1. Retries x times if an error is thrown.
  2. Has a delay of y before each retry.
  3. Emits like it wasn’t there if no error occurs.
  4. Emits the last thrown error in case x tries are exceeded. A lot of solutions were struggling especially with this.

What will we use to build the operator?

We’ll put together 4 existing RxJS operators to build our own retryWithDelay operator:

  • retryWhen: Mirrors the source observable. Maps errors into the notifier function which is provided as a parameter. If the notifier function emits a value the operator resubscribes to the source observable. Errors and completions of the notifier function are forwarded.
  • scan: Applies an accumulator function to emitted values. Provides access to the last value of the accumulator function.
  • tap: Perform a side effect for every item.
  • delay: Delay the received items by a given timeout.

How can we build our custom operator?

We’ll pipe the input observable into the retryWhen operator. In there we reuse the other 3 operators:

  1. First, we count the times the operator retried using scan. We’ll increase the count each time by one. We also overwrite the error attribute each time and keep track of the last error:
export function retryWithDelay<T>(
	  delay: number,
	  count = 1
	): MonoTypeOperatorFunction<T> {
	  return (input) =>
	    input.pipe(
	      retryWhen((errors) =>
	        errors.pipe(
	          scan((acc, error) => ({ count: acc.count + 1, error }), {
	            count: 0,
	            error: undefined as any,
	          }),
	        )
	      )
	    );
	}

#javascript #programming #angular #typescript #rxjs

RxJS: Retry With Delay — You’ll Want to Build This Operator
25.30 GEEK