Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change behavior of shareReplay #5894

Closed
davemecha opened this issue Nov 15, 2020 · 7 comments
Closed

Change behavior of shareReplay #5894

davemecha opened this issue Nov 15, 2020 · 7 comments

Comments

@davemecha
Copy link

Feature Request

Is your feature request related to a problem? Please describe.

I'm always confused by the current implementation of shareReplay because it behaves different than the share operator.

Describe the solution you'd like

It want to suggest shareReplay should reconnect to the source if the source was completed and a new observer subscribes. But not like in rxjs 5. It should still replay the last n values of the completed source on new subscription.

This is an example implementation.

function shareReplayNew<T>(count: number) {
  let lastSubject: ReplaySubject<T>;

  return function(source: Observable<T>): Observable<T> {
    return source.pipe(
      multicast(() => {
        const rs = new ReplaySubject<T>(count);
        if (lastSubject) lastSubject.forEach(v => rs.next(v));
        lastSubject = rs;
        return rs;
      }),
      refCount()
    );
  };
}

Additional context

I created a Stackblitz to demonstrate the desired behavior.

@cartant
Copy link
Collaborator

cartant commented Nov 15, 2020

Changing it (again) will break and confuse other developers: https://ncjamieson.com/whats-changed-with-sharereplay/ IMO, devs using shareReplay should be explicit about the behaviour they need and should specify the config argument. There are ESLint and TSLint rules to enforce this.

@davemecha
Copy link
Author

davemecha commented Nov 16, 2020

@cartant Thanks for your reply. I appreciate the last changes on refCount default behavior. This is quite handy.

But my suggestion is about how shareReplay behaves on source completion. I think this is independently of the refCount setting. If I understand this correctly, share is reconnecting on the source on a new subscription, even after the source completed or errored. shareReplay is not doing so. This feels kind of inconsistent to me.

I don't know how to achieve my suggested behavior by using the config argument.

@cartant
Copy link
Collaborator

cartant commented Nov 16, 2020

Completion effects unsubscription for all subscribers - dropping the ref count to zero - so the two are directly related. share only connects to the source of the ref count is being incremented from zero.

@davemecha
Copy link
Author

Sure, but the ref count drops to zero independently of the reference counting setting being active or inactive. This is what I meant with it's independently from the config setting refCount. But I definitely agree it has something to do with ref counting.

shareReplay connects to the source initially if the ref count is incremented from zero first. share does this always. This is what feels inconsistent to me.

@cartant
Copy link
Collaborator

cartant commented Nov 16, 2020

Okay, I see what you mean. The replaying of the complete notification is intentional and that's not going to change. You can get reset-on-complete behaviour using multicast:

const shared = source.pipe(
  multicast(() => new ReplaySubject(/* whatever */)),
  refCount()
);

It's likely that the multicasting infrastructure will be replaced in version 7 with something that's more flexible and will let you specify the reset-on-complete behaviour in the configuration passed to share - see #5634

However, those changes will still include a shareReplay that behaves as it does now.

@cartant
Copy link
Collaborator

cartant commented Nov 18, 2020

Closing for the reasons mentioned in the comment above.

@cartant cartant closed this as completed Nov 18, 2020
@JontyMC
Copy link

JontyMC commented Jul 13, 2021

The solution for version 7 for the equilavent of shareReplay({ refCount: true, bufferSize: 1}) with reset for completed observables is:

share({
  connector: () => new ReplaySubject(1),
  resetOnError: true,
  resetOnComplete: true,
  resetOnRefCountZero: true
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants