监控可观察而不是订户

时间:2016-02-10 21:13:07

标签: rxjs

Observables,我正在成为一个大粉丝,我的堆栈开始显示它。

我想构建一些监视工具来挂钩* n个可观察数据,并且能够识别当前订阅的数量,而不是自己的订阅者。

在一些Rx可视化库中,我注意到他们已经修复了许多运算符,看起来有点过分了吗?

2 个答案:

答案 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);
}