Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple subscriptions assigned to same Subject

Tags:

angular

rxjs

I am using a common pattern of unsubscribing to an observable when a component is destroyed. I want to know if there are any issues with reusing the same Subject across many Subscriptions? Or should I have a new subject for each subscribe call?

destroy$: Subject<void> = new Subject();  // can this be reused across many subscriptions?
    
ngOnDestroy(): void {
  this.destroy$.next();
  this.destroy$.complete();
}

getData = () => {
  serviceCall().pipe(takeUntil(this.destroy$))  // same Subject
  .subscribe(res => data = res)
}

getData2 = () => {
  serviceCall2().pipe(takeUntil(this.destroy$))  // same Subject
  .subscribe(res => data2 = res)
}
like image 519
brett Avatar asked Oct 30 '25 10:10

brett


2 Answers

There is nothing wrong with using the same subject. The only reason you might want to have different subjects associated to each subscription is when you want to be able to stop each of them individually. In your case, if you want to unsubscribe from both at the same time it is perfectly fine.

Here is an example demonstrating your approach: https://playcode.io/1750951

Another common pattern for this case is the usage of Subscription():

private readonly subscriptions = new Subscription();

ngOnDestroy(): void {
  this.subscriptions.unsubscribe():
}

getData = () => {
  const getDataSubscription = serviceCall().
  .subscribe(res => data = res)

  subscriptions.add(getDataSubscription)
}

getData2 = () => {
  const getData2Subscription = serviceCall2().
  .subscribe(res => data = res)

  subscriptions.add(getData2Subscription)
}

I tend to prefer this second approach as it is less verbose.

like image 161
Alvaro Flaño Larrondo Avatar answered Nov 02 '25 00:11

Alvaro Flaño Larrondo


There's no problem at all reusing your subject.

In doubt, check the source code:

  next(value: T) {
    if (!this._closed) {
      const { observers } = this;
      const len = observers.length;
      for (let i = 0; i < len; i++) {
        observers[i].next(value);
      }
    }
  }

You can see that when you call next, it'll itself call next for all the observers (downstreams).

That said, if you're using a fairly recent version of Angular (I think this came out in v16 or v17) you can do something a lot simpler:

this.someStream$.pipe(
  takeUntilDestroyed(inject(DestroyRef))
).subscribe()
like image 20
maxime1992 Avatar answered Nov 02 '25 00:11

maxime1992