Темы RxJava и обработка ошибок

Я пытаюсь добиться поведения, аналогичного поведению шины событий. Для моих требований подходит PublishSubject.

Субъект испускает элементы, представляющие результат некоторой глобальной операции, которая может быть успешно разрешена или завершиться ошибкой в ​​случае исключения. Я не могу использовать onNext() для успешных событий и onError() с Throwable в случае ошибки, поскольку после вызова onError() субъект завершает свою работу, и любые будущие подписчики не получат никаких выбросов, кроме onError().

Прямо сейчас, как я это вижу, мне нужно создать класс, представляющий событие, и, возможно, ссылку на Throwable в случае ошибки. Однако это кажется неразумным, поскольку приходилось бы обрабатывать ошибки внутри onNext().

Как бы вы это сделали?


person woot    schedule 29.07.2015    source источник


Ответы (1)


Создание событий обертывания универсального класса - отличный вариант. Допустим, мы называем это классом ResponseOrError, он должен в основном содержать два поля.

private T data;
private Throwable error;

и два простых заводских метода:

public static <T> ResponseOrError<T> fromError(Throwable throwable) {
    return new ResponseOrError<>(throwable);
}

public static <T> ResponseOrError<T> fromData(T data) {
    return new ResponseOrError<>(data);
}

чтобы удалить некоторый шаблонный код, вы можете предоставить Transformer, чтобы сделать Observable типа ResponseOrError.

public static <T> Observable.Transformer<T, ResponseOrError<T>> toResponseOrErrorObservable() {
    return new Observable.Transformer<T, ResponseOrError<T>>() {

        @Override
        public Observable<ResponseOrError<T>> call(final Observable<T> observable) {
            return observable
                    .map(new Func1<T, ResponseOrError<T>>() {
                        @Override
                        public ResponseOrError<T> call(final T t) {
                            return ResponseOrError.fromData(t);
                        }
                    })
                    .onErrorResumeNext(new Func1<Throwable, Observable<? extends ResponseOrError<T>>>() {
                        @Override
                        public Observable<? extends ResponseOrError<T>> call(final Throwable throwable) {
                            return Observable.just(ResponseOrError.<T>fromError(throwable));
                        }
                    });
        }
    };
}

тогда вы можете использовать это так:

final Observable<ResponseOrError<ImportantData>> compose = mNetworkService
               .getImportantData()
               .compose(ResponseOrError.<ImportantData>toResponseOrErrorObservable());

и теперь вы можете легко сопоставить результат в зависимости от успеха или неудачи или даже предоставить другой Transformer, возвращающий сопоставленный Observable ‹T> вместо Observable‹ ResponseOrError ‹T >> < / em>

person krp    schedule 29.07.2015
comment
Я не знал о compose() и Transformer до того, как вы разместили это, но на самом деле есть встроенный тип для вашего ResponseOrError типа, называемый Notification, подумал, что стоит упомянуть. - person woot; 29.07.2015
comment
Хотя это не вызывает onError, он все равно будет вызывать onComplete, и любые подписки на ваш объект будут завершены и больше не будут принимать дополнительные события. Возможно, вам будет удобнее использовать эту стратегию и что-то вроде RxRelay. github.com/JakeWharton/RxRelay - person Victor Rendina; 11.06.2018