在不包含所有项目的集合上引发错误

时间:2019-10-31 18:35:43

标签: rx-java rx-java2

我想知道最干净的方法是使用RxJava语法遍历一个集合,如果不存在任何项,就会引发错误。下面显示了一个混合示例,但理想情况下,我希望使用RxJava语法中的所有逻辑。

public Single<List<Bar>> doSomething(Collection<String> ids) {
  Single<List<Bar>> bars = getAllBars();
  List<Bar> results = bars
  .flattenAsObservable(z-> z)
  .filter(bar -> ids.contains(bar.getId())
  .toList()
  .blockingGet();// Blocking since I don't know the RxJava syntax for below

  if (results.isEmpty()) {
    throw SomeError();
  }
  if (results.size() != ids.size()) {
    // Ideally know which bar(s) are not in the ids list
    throw someError();
  }
  return Single.just(results);
}

2 个答案:

答案 0 :(得分:2)

实际上,如果您在没有找到ID的情况下向下游传播错误并在想要对该错误采取行动的任何地方订阅,则可以非常简单地实现此目的。像这样添加关于缺失栏的信息也很容易:

public Single<List<Bar>> doSomething(Collection<String> ids) {
  return getAllBars()
    .map(bars -> {
      List<Bar> unknownBars = new ArrayList<>();
      for(Bar bar : bars) {
        if(!ids.contains(bar.getId()) {
          unknownBars.add(bar);
        }
      }
      if (unknownBars.isEmpty()) {
        return bars;
      } else {
        throw new BarsNotFoundException(unknownBars);
      }
    });
}

//elsewhere
doSomething(ids)
  .subscribe(bars -> { /* do something */ }, throwable -> { /* handle error */ });

如果您的地图中到达了throw语句,则将使用您抛出的错误来执行您的subscription方法的第二个lambda。

我自己从使用rx中学到的东西:当您开始对rx感到更舒适时,它开始感觉像是一把花哨的新锤子,突然间所有东西看起来都像钉子。请记住,只有在让您的生活更轻松而不是更辛苦的时候才使用它。

答案 1 :(得分:1)

也许您也可以拥有类似的东西:

public static void main(String[] args) {
    Collection<String> ids = List.of("id4", "id2", "id1", "id3"); // same ids
    // Collection<String> ids = List.of("id4", "id2", "id1", "id5"); // different ids
    // Collection<String> ids = List.of("id4", "id2", "id1", "id3", "id5"); // different ids
    // Collection<String> ids = List.of("id4", "id2", "id1"); // different ids

    doSomething(ids)
            .subscribe(l -> System.out.println("received: " + toString((List<Bar>) l)),
                       err -> System.err.println(err.getMessage()));

    Flowable.timer(60, SECONDS) // Just to block the main thread for a while
            .blockingSubscribe();
}

private static Single<List<Bar>> doSomething(Collection<String> ids) {
    return getAllBars().flatMap(bars -> {
                           List<String> unknownBarIds = bars.stream().map(Bar::getId).collect(Collectors.toList());
                           unknownBarIds.removeAll(ids);
                           return unknownBarIds.isEmpty()
                                            ? Single.just(bars)
                                            : Single.error(new Exception("unknown bars: " + unknownBarIds));
                       })
                       .flatMap(bars -> {
                           List<String> barIds = bars.stream().map(Bar::getId).collect(Collectors.toList());
                           List<String> missingIds = new ArrayList<>(ids);
                           missingIds.removeAll(barIds);
                           return missingIds.isEmpty()
                                        ? Single.just(bars)
                                        : Single.error(new Exception("missing bars: " + missingIds));
                       });
}

private static Single<List<Bar>> getAllBars() {
    return Single.just(List.of(new Bar("id2"), new Bar("id1"), new Bar("id3"), new Bar("id4")));
}

private static String toString(final List<Bar> bars) {
    return bars.stream().map(Bar::getId).collect(Collectors.joining(", "));
}

如果您希望将错误保留在rx流中?