从外部RxJava2处理订阅服务器中的异常

时间:2018-07-20 13:35:51

标签: rx-java2

我遇到了一个问题,试图处理可能在RxJava2 Observable的订阅服务器内部发生的异常,但是我无法在内部处理。

因此,我需要的是一种建立订户的方法,如果它未能引发异常-RxJava非常渴望获取异常并将其抛出到其他任何地方,但是我希望在其他地方...(这是很好,只要我可以在doOnError中进行处理...)

我知道the spec,但这对我没有帮助。 (并且一个空的ErrorHandler只是会吞下,但不会直接抛出。)

因此,在一些示例中,我尝试引发Exception,我的目标是将其捕获在主要方法的捕获子句中……但是RxJava的ErrorHandler窃取了它。

倒数第二个示例是(我认为很丑)的解决方法-还有其他想法吗?尤其是因为该解决方法不适用于Single。

谢谢!

import io.reactivex.Observable;
import io.reactivex.plugins.RxJavaPlugins;

import java.util.concurrent.atomic.AtomicReference;

public class RxEmittingException {

    static Observable<Integer> observable = Observable.just(2, 1, 0);

    public static void main(String[] args) {

        // without changing this, the behaviour is the same, but it's more readable like this.
        RxJavaPlugins.setErrorHandler(t -> System.out.println("[RxErrorHandler] >>> " + t));

        /*
        My intention is to trigger the catches below printing 'Method failed: ...'!
         */

        try {
            System.out.println("doSomeDangerousDivision");
            doSomeDangerousDivision(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.err.println("Method failed: " + e);
        }

        try {
            System.out.println("doSomeDangerousDivisionWithErrorHandler");
            doSomeDangerousDivisionWithErrorHandler(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.err.println("Method failed: " + e);
        }

        try {
            System.out.println("doSomeSingleDangerousDivision");
            doSomeSingleDangerousDivision(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.err.println("Method failed: " + e);
        }

        try {
            System.out.println("doSomeSingleDangerousDivisionWithErrorHandler");
            doSomeSingleDangerousDivisionWithErrorHandler(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.err.println("Method failed: " + e);
        }

        try {
            System.out.println("workaround");
            workaround(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.err.println("Method failed: " + e);
        }

        try {
            System.out.println("workaroundSingle");
            workaroundSingle(4);
            System.out.println("~~fail~~\n");
        } catch (Throwable e) {
            System.out.println("Method failed: " + e);
        }
    }


    private static void doSomeDangerousDivision(int dividend) throws Throwable {
        observable.subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)));
    }

    private static void doSomeDangerousDivisionWithErrorHandler(int dividend) throws Throwable {
        observable.subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)), throwable -> {
            System.out.println("catch and rethrow: " + throwable);
            throw new RuntimeException(throwable);
        });
    }

    private static void doSomeSingleDangerousDivision(int dividend) throws Throwable {
        observable.lastOrError().subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)));
    }

    private static void doSomeSingleDangerousDivisionWithErrorHandler(int dividend) throws Throwable {
        observable.lastOrError()
                  .subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)), throwable -> {
                      System.out.println("catch and rethrow: " + throwable);
                      throw new RuntimeException(throwable);
                  });
    }

    private static void workaround(int dividend) throws Throwable {
        AtomicReference<Throwable> t = new AtomicReference<>();
        observable.subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)), throwable -> {
            System.out.println("catch and assign: " + throwable);
            t.set(throwable);
        });
        System.out.println("Extracted Throwable: " + t.get());
        if (t.get() != null) {
            throw t.get();
        }
    }

    private static void workaroundSingle(int dividend) throws Throwable {
        AtomicReference<Throwable> t = new AtomicReference<>();
        observable.lastOrError()
                  .subscribe(divisor -> System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor)), throwable -> {
                      System.out.println("catch and assign: " + throwable);
                      t.set(throwable);
                  });
        System.out.println("Extracted Throwable: " + t.get());
        if (t.get() != null) {
            throw t.get();
        }
    }

}

输出为:

doSomeDangerousDivision
4/2=2
4/1=4
[RxErrorHandler] >>> io.reactivex.exceptions.OnErrorNotImplementedException: / by zero
~~fail~~

doSomeDangerousDivisionWithErrorHandler
4/2=2
4/1=4
catch and rethrow: java.lang.ArithmeticException: / by zero
[RxErrorHandler] >>> io.reactivex.exceptions.CompositeException: 2 exceptions occurred.
~~fail~~

doSomeSingleDangerousDivision
[RxErrorHandler] >>> io.reactivex.exceptions.UndeliverableException: java.lang.ArithmeticException: / by zero
~~fail~~

doSomeSingleDangerousDivisionWithErrorHandler
[RxErrorHandler] >>> io.reactivex.exceptions.UndeliverableException: java.lang.ArithmeticException: / by zero
~~fail~~

workaround
4/2=2
4/1=4
catch and assign: java.lang.ArithmeticException: / by zero
Extracted Throwable: java.lang.ArithmeticException: / by zero
Method failed: java.lang.ArithmeticException: / by zero

workaroundSingle
[RxErrorHandler] >>> io.reactivex.exceptions.UndeliverableException: 
java.lang.ArithmeticException: / by zero
Extracted Throwable: null
~~fail~~

0 个答案:

没有答案