做运营商而不是整个订户

当你只需要OnNext()仅仅因为它更具可读性时,使用Action而不是整个Subscriber是非常有吸引力的。 但是,当然会发生错误,如果您只使用Action1 ,您的应用程序中会出现Exception 。 在这里, 运营商可以提供帮助。 我只关心这两种方法是完全一样的,请确认或否认。 任何陷阱?

第一种方法:

 Observable .just(readFromDatabase()) .doOnError(new Action1() { @Override public void call(Throwable throwable) { // handle error } }).subscribe(new Action1() { @Override public void call(SomeData someData) { // react! } }); 

第二种方法:

 Observable .just(readFromDatabase()) .subscribe(new Subscriber() { @Override public void onCompleted() { // do nothing } @Override public void onError(Throwable e) { // handle error } @Override public void onNext(SomeData someData) { // react! } }); 

谢谢!

两种方法都不尽相同,你会从第一种方法中得到一些惊喜:

第一个惊喜是doOnError不消耗错误,但只对它执行一些操作。 因此,在您的情况下,如果流生成错误,它将通过您的doOnError代码,并在此之后触发OnErrorNotImplementedException ,就像doOnError步骤不存在一样。

假设你意识到这一点,并为你的订阅调用添加一个空的error handling程序:

 Observable .just(readFromDatabase()) .doOnError(...) .subscribe(..., error -> { /* already handled */ } ); 

然后你就可以遇到下一个微妙的差异。 do*块被认为是流的一部分,这意味着块中任何未捕获的exception都将导致流错误(与’onNext / OnError / onComplete’块中抛出的exception相反,它们被忽略或立即抛出,取消他们的订阅方式)。

所以在上面的示例中,如果我们说你的数据库读取触发了一个流错误A ,它被传递给doOnError块,它抛出一个exceptionB ,那么我们添加的(空)订阅error handling程序将收到B (并且只有B ) 。

稍后的差异对于doOnError并不是非常关注(因为无论如何流都被终止),但是在doOnNext出现时可能会非常令人惊讶,其中exception与订阅onNext块中抛出的相同exception具有非常不同的行为(错误的流与隐式取消的流)。