Intro

When I just started learning RxJS a few years ago it was not so obvious for me why we have two operators in RxJS for doing repeat logic. Not only I may have such a question, so in this article, I will review both retry and repeat operators as well as possible use-cases for them.

retry…or repeat?

In RxJS both repeat and retry operators allow you to conditionally re-subscribe terminated source observable they were applied to.

Both of them make source observable sequence will be restarted.

The main distinction is

repeat — resubscribes when it receives onComplete(), but not by error.

retry — resubscribes when it receives onError().

In terms of possible use-cases:

If you want to repeat SUCCESSFUL data fetching wrapped in observable — use repeat.

If you want to repeat FAILED data fetching wrapped in observable — use retry.

Now let’s take a closer look at each of them with examples.

retry

retry(count)

It returns the Observable that mirrors the source Observable with the exception of an error.

If the source Observable calls error, this method will resubscribe to be source Observable for a maximum of count re-subscriptions

count — Number of retry events before failing. Default is -1.

retry marble diagram

Here is vanilla JS example for dealing with an unstable network connection. we make observable-wrapped Ajax call and use retry operator. in case first Ajax call returns error retry operator will re-do an ajax request three more times.

if one of these attempts is successful it will provide data for onNext subscribers callback.

if all three additional attempts fail then an error will be propagated to subscribers onError callback handler.

Let's try to run it in a codepen.

And as you can see — we have one failed requests and 4 more retry attemps (they all failed as well since for learning purposes we were trying to reach non-existing url).

To conclude:

retry returns Observable that mirrors the source Observable. If source Observable calls error, this method will resubscribe to the source Observable (repeat running source sequence) for a maximum of count param value re-subscriptions. If one of the retries runs succeeded — event data will be provided to onNext callback handlers of subscribers. If all retry runs fail — an error will be propagated to onError handlers. One of the possible use-cases — ajax failed requests retry.

repeat

repeat(count)

Returns an Observable that repeats the stream of items emitted by the source Observable at most count times.

count — The number of times the source Observable items are repeated, a count of 0 will yield an empty Observable. Default is -1.

repeat marble diagram

Look at this example:

We take source sequence and run it twice.

Notice that repeat operator treats the initial run as the first one.

Now let’s take a look at more complicated use-case — say, we have a back-end, but it brings not all data at once but by pages. So let’s implement a fetching of a specific number of paginated data portions from a back-end:

Before I describe this code — pay attention that we wrapped source observable in defer functions from RxJS. Each time when repeat operator re-run source observable — defer will fun its factory function — so our url will have updated counter value. You can read more about defer here

Lets now observe how it works:

When we subscribe source makes first call with page = 0 (counter variable). After data successfully fetched, we emit data to subscribers. And then source observable completes — so repeat starts working — and re-run source — it is defer function in our case. Defer function calls its factory function and returns ajax observable with new counter value. So now we requesting API with page = 1. New page of data is emitted to subscribers as well.

You can try to run this code yourself in a codepen.

To conclude:

repeat returns an Observable that repeats the stream of items emitted by the source Observable at most count times. count param — the number of times the source Observable items are repeated, a count of 0 will yield an empty Observable. Unlike retry — repeat operator treats initial source$ run as the first try, so the source will be repeated (count — 1) times. repeat — resubscribes when it receives onComplete() from source sequence, but not by error. If you need source observable to repeat with different params — use RxJS defer function.

Can we use them together?

Can we use these both retry and repeat?

Definitely yes! If you want to repeat source requests and retry if one of the repeated calls failed — you can use both operators.

Here in this example, we request paginated information twice with repeat operator. If some of the requests fail — retry will re-run it.

retryWhen and repeatWhen

When I first saw retry and repeat operators examples my thought was — can I add some delay between retried ajax calls?

And this is when operators retryWhen and repeatWhen come into play — but this is the topic of another article — let’s keep in touch!

Other links: