如何使用Retrofit + RxJava处理来自并行Web请求的错误?

时间:2018-10-18 01:29:48

标签: retrofit2 rx-java2

在这种情况下,我会并行发出一些Web请求。有时我打这些电话,所有请求都遇到相同的错误(例如,无网络):

void main() {
    Observable.just("a", "b", "c")
            .flatMap(s -> makeNetworkRequest())
            .subscribe(
                    s -> {
                        // TODO
                    },
                    error -> {
                        // handle error
                    });
}

Observable<String> makeNetworkRequest() {
    return Observable.error(new NoNetworkException());
}

class NoNetworkException extends Exception {
}

根据时间,如果一个请求在其他请求发出之前发出NoNetworkException,则Retrofit / RxJava将处置/中断其他请求。对于每个仍在进行中的请求,我将看到以下日志之一(不是全部三个):

<-- HTTP FAILED: java.io.IOException: Canceled
<-- HTTP FAILED: java.io.InterruptedIOException
<-- HTTP FAILED: java.io.InterruptedIOException: thread interrupted

我将能够处理订户中的NoNetworkException错误,下游的所有内容都将得到处理,一切正常。

但是,基于计时,如果两个或更多 Web请求发出NoNetworkException,则第一个将触发上述事件,并处理所有下游事件。第二个NoNetworkException无处可去,我将得到可怕的UndeliverableException。这与记录在here中的示例#1相同。

在以上文章中,作者建议使用错误处理程序。如果我希望再次听到相同的错误,显然retry / retryWhen没有任何意义。我不了解onErrorResumeNext / onErrorReturn在这里有什么帮助,除非我将它们映射到可恢复的东西以在下游处理:

Observable.just("a", "b", "c")
        .flatMap(s ->
                makeNetworkRequest()
                        .onErrorReturn(error -> {
                            // eat actual error and return something else
                            return "recoverable error";
                        }))
        .subscribe(
                s -> {
                    if (s.equals("recoverable error")) {
                        // handle error
                    } else {
                        // TODO
                    }
                },
                error -> {
                    // handle error
                });

但这似乎很奇怪。

我知道另一种解决方案是使用RxJavaPlugins.setErrorHandler()设置全局错误处理程序。这似乎也不是一个很好的解决方案。我可能想在应用的不同部分处理NoNetworkException

那么我还有什么其他选择?在这种情况下其他人会做什么?这一定很常见。

**我不完全了解谁在打扰/处置谁。 RxJava是否在平面图中处理所有其他请求,这又导致Retrofit取消请求?还是Retrofit取消请求,导致每个 平面图中的请求发出上述IOException之一?我想回答这个问题并不重要,只是好奇。

++可能并非所有的a,b和c请求都在执行中,具体取决于线程池。

1 个答案:

答案 0 :(得分:1)

您是否尝试过使用带有delayErrors = true的flatMap()?