Как обрабатывать ошибки от параллельных веб-запросов, используя Retrofit + RxJava? - PullRequest
0 голосов
/ 18 октября 2018

У меня есть такая ситуация, когда я делаю несколько веб-запросов параллельно.Иногда я делаю эти вызовы, и все запросы видят одну и ту же ошибку (например, отсутствие сети):

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 в подписчике, и все последующие потоки будут удаленыи все в порядке.

Однако, исходя из времени, если два или более веб-запроса испускают NoNetworkException, то первый вызовет вышеуказанные события, уничтожая все в нисходящем направлении.Второму NoNetworkException некуда будет идти, и я получу страшный UndeliverableException.Это то же самое, что описано в примере № 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 избавляется от всех других запросов в flatmap, что, в свою очередь, заставляет Retrofit отменять запросы?Или Retrofit отменяет запросы, в результате чего каждый запрос в плоской карте испускает одно из указанных выше исключений IOException?Я думаю, что на самом деле не имеет значения отвечать на вопрос, просто любопытно.

++ Возможно, что не все запросы a, b и c выполняются в зависимости от пула потоков.

1 Ответ

0 голосов
/ 29 октября 2018

Вы пробовали использовать flatMap () с delayErrors = true?

...