RxSwift: share vs replay vs shareReplay

A common beginner error with Rx is forgetting that each subscription to an observable re-executes the chain of operators:

let results = query.rx.text
.flatMapLatest { query in
results.subscribe(...)   // a network request
results.subscribe(...) // another network request

We have multiple subscriptions to the same Observable but don’t want the observable to re-execute for each subscription. RxSwift has several operators for this: share(), replay(), replayAll(), shareReplay(), publish(), and even shareReplayLatestWhileConnected(). Which one to use?

Here’s a summary of the properties of these operators:

1 Replays at most bufferSize events 2 Replays one event while reference count of subscribers > 0

Shared subscription: The returned observable shares a single underlying subscription to the source observable. This is the case for all of these operators.

Connectable: The returned observable does not push events until the connect() function is called. This allows multiple subscribers to subscribe before any events are sent.

Reference counting: The returned observable reference counts the number of subscribers it has. When the number of subscribers goes from zero to one, subscribes to the source observable. When the number goes from one to zero, unsubscribe and dispose the source observable. Note: the underlying observable will be re-subscribed each time the number of subscribers goes to zero to one. However there will never be more than one subscription to the source observable at a time, and all concurrent subscribers will share the same subscription to the source observable. If the underlying observable completes or send an error, the underlying observable might not be re-subscribed. This is a gray area I suggest avoiding, which can be done by ensuring there are no further subscribers after the reference count drops to zero.

Replays events: The operator will replay events from the source observable to subscribers who after those events are sent. For replay(bufferSize) and shareReplay(bufferSize), the number of events is at most bufferSize. For shareReplayLatestWhileConnected(), at most one event is replayed. When the reference count of subscribers drops to zero, the replay buffer is cleared. Therefore subscribers that cause the reference count to go from zero to one do not get an event replayed.

There are also multicast operators which can be used if you have Subjects. But the operators described here are the most popular and most likely to be useful for most applications.