使用迭代器进行RxJava Zip运算符错误处理

时间:2016-08-02 15:25:05

标签: android rx-java

背景

我有一个使用RxJava根据列表从不同位置获取数据的进程。每个项目都通过一个不同的方法(所有返回的Observables。)。由于要使用逻辑运算符的N个项是带有迭代器的zip

问题

下面的代码按预期工作,但似乎"错误"我需要一个try-catch块来捕获getBigFoo()引发的异常 - 它返回FooNotFoundException。其他与错误无关的运算符是否包含此内容,例如onErrorResumeNext()onErrorReturn()

private Observable<Bar> processFoos(List<Foo> foos) {

        List<Observable<? extends IBar>> observablesToZip = new ArrayList<>();

        for(Foo foo : foos) {

            switch (foo.getType()) {

                case BIG_FOO :

                    try {
                        observablesToZip.add(getBigFoo(foo.getId()));
                    } catch (Exception exception) {
                        //do nothing - but this seems wrong
                    }
            }
        }

        return Observable.zip(observablesToZip, results -> mergeFoosIntoBar(results));
    }

尝试

下面的尝试似乎没有捕获生成的异常。我不明白为什么因为序列中技术上没有上游或下游项目,所以Observable.empty()应该有用吗?

private Observable<Bar> processFoos(List<Foo> foos) {

        List<Observable<? extends IBar>> observablesToZip = new ArrayList<>();

        for(Foo foo : foos) {

            switch (foo.getType()) {

                case BIG_FOO :
                   observablesToZip.add(getBigFoo(foo.getId().onErrorResumeNext(Observable.empty()));
            }
        }

        return Observable.zip(observablesToZip, results -> mergeFoosIntoBar(results));
    }

3 个答案:

答案 0 :(得分:1)

您可能想要使用defergetBigFoo不应该抛出异常,而是返回错误的Observable。因此defer可以帮助您解决问题:

Observable<IBar> obs = Observable.defer(() -> {
             try {
                 return getBigFoo(foo.getId());
              } catch (Exception ex) {
                  return Observable.error(ex);
              } 
});
observablestoZip.add(obs);

答案 1 :(得分:1)

@dwursteisen得到了正确答案,但并不完全在那里。

我的问题是我抛出了一个新的FooNotFoundException:

throw new FooNotFoundException()

但我需要做的是:

return Observable.error(new FooNotFoundException());

然后在我的Zip功能中:

observablesToZip.add(getBigFoo(foo.getId())).onExceptionResumeNext(Observable.just(null);

使用上述组合意味着整个序列不会中止并在单个Observables被解析时返回错误并可能引发错误。

答案 2 :(得分:0)

你能使getBigFoo(foo.getId())抛出RuntimeException而不是Exception吗?必须捕获管道上的所有异常,但不捕获runtimeExceptions。

看看这个愚蠢的例子

         /**
 * Here is a silly example how runtimeExceptions are not needed
 */
@Test
public void observableRuntimeException() {
    Integer[] numbers = {0, 1, 2, 3, 4, 5};

    Observable.from(numbers)
              .doOnNext(number -> throwRuntimeException())
              .doOnError(t -> System.out.println("Expecting illegal argument exception:" + t.getMessage()))
              .subscribe();

}

private void throwRuntimeException() {
    throw new RuntimeException();
}

您可以在此处查看更多示例https://github.com/politrons/reactive