我定义了一个像这样的Observable:
const obs$ = Observable.create(...)
.publishReplay(1)
.refCount();
因此它在我的源Observable和所有观察者之间放置一个ReplaySubject(1)。
由于ReplaySubject在其状态中具有观察者数量(通过其observers
数组属性),如何从obs$
访问ReplaySubject?
我实际上只需知道obs$
是否有观察员。 RxJS4在Subject上有a hasObservers() method,但它在RxJS5中删除了。我怎样才能用RxJS5实现这个目标?
答案 0 :(得分:2)
不确定您的用法,但根据我的需要,我创建了一个自定义操作符,允许我根据refCount的状态透明地执行副作用(类似于点击)。它只是进行传递订阅并对子/ unsub进行打孔。回调获取当前的refCount和前一个,以便您可以告诉状态和方向。我喜欢使用运算符,因为我可以在流中的任何位置插入它。如果您只是想要一个二进制输出,是否有任何订阅,可以很容易地修改它。
const { Observable, Observer, interval } = rxjs;
const { publishReplay, refCount } = rxjs.operators;
const tapRefCount = (onChange) => (source) => {
let refCount = 0;
// mute the operator if it has nothing to do
if (typeof onChange !== 'function') {
return source;
}
// mute errors from side-effects
const safeOnChange = (refCount, prevRefCount) => {
try {
onChange(refCount, prevRefCount);
} catch (e) {
}
};
// spy on subscribe
return Observable.create((observer) => {
const subscription = source.subscribe(observer);
const prevRefCount = refCount;
refCount++;
safeOnChange(refCount, prevRefCount);
// spy on unsubscribe
return () => {
subscription.unsubscribe();
const prevRefCount = refCount;
refCount--;
safeOnChange(refCount, prevRefCount);
};
});
};
const source = interval(1000).pipe(
publishReplay(1),
refCount(),
tapRefCount((refCount, prevRefCount) => { console.log('refCount', refCount, prevRefCount > refCount ? 'down': 'up'); })
);
const firstSub = source.subscribe((x) => { console.log('first', x); });
let secondSub;
setTimeout(() => {
secondSub = source.subscribe((x) => { console.log('second', x); });
}, 1500);
setTimeout(() => {
firstSub.unsubscribe();
}, 4500);
setTimeout(() => {
secondSub.unsubscribe();
}, 5500);
<script src="https://unpkg.com/rxjs@rc/bundles/rxjs.umd.min.js"></script>
打字稿版本:
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
export const tapRefCount = (
onChange: (refCount: number, prevRefCount: number) => void
) => <T>(source: Observable<T>): Observable<T> => {
let refCount = 0;
// mute the operator if it has nothing to do
if (typeof onChange !== 'function') {
return source;
}
// mute errors from side-effects
const safeOnChange = (refCount, prevRefCount) => {
try {
onChange(refCount, prevRefCount);
} catch (e) {
}
};
// spy on subscribe
return Observable.create((observer: Observer<T>) => {
const subscription = source.subscribe(observer);
const prevRefCount = refCount;
refCount++;
safeOnChange(refCount, prevRefCount);
// spy on unsubscribe
return () => {
subscription.unsubscribe();
const prevRefCount = refCount;
refCount--;
safeOnChange(refCount, prevRefCount);
};
}) as Observable<T>;
};
答案 1 :(得分:1)
Subject
类有一个名为observers
的公共属性(请参阅https://github.com/ReactiveX/rxjs/blob/5.5.10/src/Subject.ts#L28)
所以你可以使用:
const s = new Subject();
...
if (s.observers.length > 0) {
// whatever
}
请注意refCount
会返回一个Observable,因此您无法完成我上面提到的操作。但是,您可以将自己的主题实例作为第三个参数提供给publishReplay
,并在其上使用s.observers
,请参阅http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-publishReplay