Observables,我正在成为一个大粉丝,我的堆栈开始显示它。
我想构建一些监视工具来挂钩* n个可观察数据,并且能够识别当前订阅的数量,而不是自己的订阅者。
在一些Rx可视化库中,我注意到他们已经修复了许多运算符,看起来有点过分了吗?
答案 0 :(得分:2)
你可以创建一个我认为可以做到的运算符(免责声明:未经测试):
Rx.Observable.prototype.activeSubscriptions = (subscriptionObserver) => {
var source = this, subscriberCount = 0;
return Rx.Observable.create((observer) => {
var sharedSource = source.publish();
var d1 = sharedSource.subscribe(observer);
var d2 = sharedSource.subscribe(
null,
(e) => subscriptionObserver.onError(e),
() => subscriptionObserver.onCompleted()
);
var d3 = Disposable.create(() => subscriptionObserver.onNext(--subscriberCount));
var d4 = sharedSource.connect();
subscriptionObserver.onNext(++subscriberCount);
return new NaryDisposable([d1, d2, d3, d4]),
});
};
然后可以这样使用:
var subscriptionObserver = Rx.Observer.create((x) => console.log("Current #: " + x);
Rx.Observable.fromEvent($button, 'click')
.map(e => /*Map a value*/)
.flatMap(x => $.get(`search?q=${x.value}`))
.activeSubscriptions(subscriptionObserver)
.subscribe();
这主要是我将采取的方法的天真实施。它不会非常高效(因为您需要采用更加性能导向的方法,因为其他一些运营商正在使用)。这种方法的一个警告是,如果您在multicast
风格的上游使用它,您将只会看到一个订阅者,因为这些运算符的实现是共享订阅。
答案 1 :(得分:0)
不确定来自doOnXXX
系列的这些副作用运算符是否可用于RxJS。无论如何,这里的想法是如何在单个可观察的RxJava中实现这一点:
final Subject<Upd, Upd> monitorSubj = ReplaySubject.create();
Observable.just("one", "two")
// ....
.doOnSubscribe(() -> monitorSubj.onNext(Upd.SUBSCRIBE))
.doOnUnsubscribe(() -> monitorSubj.onNext(Upd.UNSUBSCRIBE))
// ....
.subscribe(System.out::println);
monitorSubj.subscribe(new Subscriber<Upd>() {
private int num = 0;
@Override
public void onNext(final Upd upd) {
switch (upd) {
case SUBSCRIBE:
num++;
break;
case UNSUBSCRIBE:
num--;
break;
}
System.out.println("subscribers change : num = " + num);
}
@Override
public void onCompleted() {
// ...
}
@Override
public void onError(Throwable e) {
// ...
}
});
其他doOnXXX
运算符也可能对您的任务有用。
当然,您可以在没有monitorSubj
的情况下执行相同操作,只需直接调用相应的更新处理代码即可。但是你应该考虑处理代码的线程安全性,因为它可能被多个线程调用。
private int num = 0;
private final synchronized void handleUpd(final Upd upd) {
switch (upd) {
case SUBSCRIBE:
num++;
break;
case UNSUBSCRIBE:
num--;
break;
}
System.out.println("subscribers change : num = " + num);
}
public void run() {
Observable.just("one", "two")
// ....
.doOnSubscribe(() -> handleUpd(Upd.SUBSCRIBE))
.doOnUnsubscribe(() -> handleUpd(Upd.UNSUBSCRIBE))
// ....
.subscribe(System.out::println);
}