rxjs
rxjs copied to clipboard
`observers` should be private on Subjects.
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
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 @leggechr Is it already taken issue?
I can create pull request and mark it as deprecated
.
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.
I would imagine the introduction of an isObserved
property/getter/method could be a replacement.
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?
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?
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);
});
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 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?
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.