rxjs icon indicating copy to clipboard operation
rxjs copied to clipboard

`observers` should be private on Subjects.

Open benlesh opened this issue 4 years ago • 10 comments

It was never meant as a means of introspecting or mutating what was going on within a Subject. IIRC, it was left public >6 years ago so we could access it within our own tests. That it was ever public is unfortunate.

Related #5961

benlesh avatar Jan 19 '21 22:01 benlesh

After talking with @leggechr, I think so many people are using observers that we can only deprecate it for now. The use cases seem to mostly be around if (subject.observers.length > 0) { }, or like "do you have observers? then do x, otherwise do y".

benlesh avatar Jan 19 '21 22:01 benlesh

@benlesh @leggechr Is it already taken issue? I can create pull request and mark it as deprecated.

KamilSocha91 avatar Jan 28 '21 11:01 KamilSocha91

Seems deprecated right now in v7 (without any notice in the changelog or documentation in the 6-7 change summary document:

https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L18:L19

Is there an associated api recommend for the common use case of:

if (subject.observers.length > 0) { }

It is hard to imagine any other reasonable use case.

bbarry avatar May 07 '21 19:05 bbarry

I would imagine the introduction of an isObserved property/getter/method could be a replacement.

backbone87 avatar May 08 '21 14:05 backbone87

I'm using following construction to check whether I can close an observed connection via sse (user could have multiple browser tabs opened and connected).

complete(id: string, completeAll = false) {
    const subject = this.subjectMap.get(id);

    if (subject && (completeAll || subject.observers.length < 2)) {
      subject.complete();
      this.subjectMap.delete(id);
    }
}

Seems like isObserved wouldn't do it for me. Are there any workarounds for such a case?

dmitrii334 avatar Sep 13 '22 17:09 dmitrii334

I find this property useful for unit test to check the subscriber count. Is there another recommended way to check subscriber count for test if this is deprecated?

Jonathan002 avatar Dec 30 '22 02:12 Jonathan002

I just found out this is going to be killed in the future. I was trying to build an operator that only emits to the last registered observer. Is there another way to do it?

This would be the exact example of it:

import { Observable, Subject, interval, take } from 'rxjs';

const triggerOnlyToLast = <T>() => {
  return (source$: Observable<T>) => {
    const subject$ = new Subject();

    const subscription = source$.subscribe({
      ...subject$,
      next: (val) => {
        if (!subject$.observed) {
          subscription.unsubscribe();
          return;
        }

        const last = subject$.observers.at(-1);
        last.next(val);
      },
    });

    return subject$;
  };
};

const obs$ = interval(1000).pipe(take(5), triggerOnlyToLast());

obs$.subscribe((val) => console.log('From one:', val));
const sub = obs$.pipe(take(3)).subscribe((val) => {
  console.log('From two:', val);
});

rgolea avatar Feb 22 '23 05:02 rgolea

I've just seen this deprecation, we too do the old if (this.mySubject.observers.length > 0) trick :)

So if this is to be removed, we definitely need a solution for this problem. For us, the "isObserved" proposal would work fine.

-EDIT-

Oh I've just seen a note that said "use subject.observed instead".

I checked and .observed is present, and the code underneath literally does the observers.length > 0 thing, so that's good.

ie. this problem has been solved and this issue could perhaps be closed (with the exception of dmitrii334's problem of checking if it's < 2) ?

sam-s4s avatar Jun 20 '23 00:06 sam-s4s

@sam-s4s in general, anything related to getting the observers. I was thinking that maybe a readonly array could help exposing it again or a proxy to the array?

rgolea avatar Jun 20 '23 10:06 rgolea

That could be a possibility. I'm not entirely sure why there seems to be this hidden rule to obfuscate the inner workings of rxjs objects. Sometimes you need to create wrapper objects to keep track of things, and I'm not sure why this can't just be a feature of the library.

sam-s4s avatar Jun 21 '23 04:06 sam-s4s