How to have both ReplaySubject and BehaviorSubject functionality

302 views Asked by At

I have the following code:

class MyClass {
  private readonly clientId$: ReplaySubject<string>;

  public get clientId(): Observable<string> {
    return this.clientId$;
  }

  constructor([... things]) {
    this.clientId$ = new ReplaySubject<string>(1);
    
    someObservable
      .pipe(
        map(arg => {
          // business logic and what not...
        }))
      .subscribe(clientId => {
        this.clientId$.next(clientId);
      });
  }
}

I want to be able to use myClassInstance.clientId.value(); e.g. like a behavior subject. In addition to new subscribers of clientId getting the old value since someObservable fires infrequently.

Any ideas? Thank you in advance!

1

There are 1 answers

5
BizzyBob On

While this doesn't answer your question directly, I wanted to point out that you probably don't need a subject at all!

Subscribing to an observable, just to emit the value into your own subject is not usually necessary.

In your case, you don't need the ReplaySubject, you don't need the getter, and you don't need to subscribe in your constructor.

This should do the job:

class MyClass {
    constructor(private someService:SomeService) { }

    clientId$ = this.someService.someObservable.pipe(
        map(val => val.clientId)
    );
}

As far as accessing the latest value... you could stash it in a local variable:

clientId$ = this.someService.someObservable.pipe(
    map(val => val.clientId),
    tap(clientId => this.clientId = clientId)
);

But often times that isn't necessary either. If you're using the async pipe in your template, you get the unwrapped latest value already.

<h3 *ngIf="clientId$ | async as clientId">{{ clientId }}</h3>