在 RxAndroid 中,是否有可能在调用方法中重新抛出错误?

huangapple go评论72阅读模式
英文:

Is it possible to re-throw an error in the calling method in RxAndroid?

问题

受到 .Net TPL 的启发,我正在尝试找到一种在 RX 管道之外处理错误的方法。具体来说,发生错误时,我希望观察者管道停止,并将控制权传递回周围的方法。类似于:

public void testRxJava() {
    try {
        Observable.range(0, 5)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .map(i -> { throw new RuntimeException(); })
            .subscribe();
    } catch (Exception ex) {
        // 我本来希望能在主线程执行到这里,但实际上却崩溃了
        Log.i("Test", "永远不会执行到这里");
    }
}

这将导致应用程序崩溃,并出现 io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException,它不会在 catch 子句中捕获,而是会调用主线程的 uncaughtException() 处理程序。

尝试从 subscribe() 中的错误处理程序中抛出也不起作用,同样会回退到 uncaughtException() 处理程序。

是否有一种重新抛出或以其他方式将错误信息传递给调用方法的方法?

有关 C# 的类似问题可以在 此处 找到。

英文:

Inspired by .Net TPL, I'm trying to find a way to handle an error outside the RX pipe. Specifically, on error, I wish the Observer pipe to stop, and pass control back to the surrounding method. Something like:

public void testRxJava() {
    try {
        Observable.range(0, 5)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .map(i -> { throw new RuntimeException(); })
            .subscribe();
    } catch (Exception ex) {
        // I was hoping to get here on the main thread, but crashed instead
        Log.i("Test", "Will never get here");
    }
}

This will cause the application to crash with an io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException, which will not be caught in the catch clause, and will instead invoke the main thread's uncaughtException() handler.

Trying to throw from the error handler in subscribe() does not work either, again falling back to the uncaughtException() handler.

Is there a way to re-throw or otherwise pass the error information to the calling method?

A similar question for C# is found here.

答案1

得分: 1

以下是您提供的内容的翻译:

这是我最终的做法。据我所知,这是离开ReactiveX管道并让周围的代码处理错误的唯一方法。如果有人有更优雅的方法,我会很高兴:

public void testRxJava() {
    try {
        // 如果没有错误,将为null;如果有错误,将保存Throwable
        AtomicReference<Throwable> opError = new AtomicReference<>(null);

        Observable.range(0, 5)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .map(i -> { throw new RuntimeException(); }) // 抛出异常
            .blockingSubscribe(
                result -> Log.i(TAG, "永远不会发生"),
                error -> { opError.set(error); } // 设置对错误的引用,而不会使应用崩溃
            );

        // 重新抛出异常
        if(opError.get() != null) {
            throw new Exception(opError.get());
        }

    } catch (Exception ex) {
        Log.e("Test", "异常", ex);
    }
}

请注意,翻译是基于您提供的源代码进行的。如果您有任何其他需要帮助的地方,请随时提问。

英文:

Here's what I ended up doing. As far as I can tell, this is the only way to leave the ReactiveX pipe, and let the surrounding code handle the error. Would be happy if someone has a more elegant way:

public void testRxJava() {
    try {
        // will be null if no error, will hold a Throwable on error
        AtomicReference&lt;Throwable&gt; opError = new AtomicReference&lt;&gt;(null);

        Observable.range(0, 5)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .map(i -&gt; { throw new RuntimeException(); }) // throws
            .blockingSubscribe(
                result -&gt; Log.i(TAG, &quot;will never happen&quot;),
                error -&gt; { opError.set(error); } // sets reference to the error without crashing the app
            );

        // re-throw
        if(opError.get() != null) {
            throw new Exception(opError.get());
        }

    } catch (Exception ex) {
        Log.e(&quot;Test&quot;, &quot;exception&quot;, ex);
    }
}

答案2

得分: 0

你尝试过像这样捕捉错误吗?

Observable.range(0, 5)
    .subscribeOn(Schedulers.newThread())
    .doOnError {
        // 在这里捕捉到错误
    }         
    .observeOn(AndroidSchedulers.mainThread())
    .map({ i -> throw RuntimeException() })
    .subscribe()
英文:

Have you tried catching the error like so

    Observable.range(0, 5)
        .subscribeOn(Schedulers.newThread())
        .doOnError {
            //your error caught here
        }         
        .observeOn(AndroidSchedulers.mainThread())
        .map({ i -&gt; throw RuntimeException() })
        .subscribe()

huangapple
  • 本文由 发表于 2020年10月1日 01:20:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/64142690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定