如何根据结果消耗终结点乘法时间

时间:2019-09-10 12:27:54

标签: rx-java2 vert.x

尝试使用返回{"next": boolean, "result": [some data]}的端点,其中“ next”表示存在更多数据/页面。 我们使用vert.x的Web客户端和rxjava api,到目前为止,成功完成了以下代码:

public Single<JsonArray> getData() {
    return Observable
            .range(1, Integer.MAX_VALUE)
            .flatMapSingle(page -> Single.just(webClient.getAbs(API_URL + "?page=" + page)
                        .rxSend()
                        .subscribeOn(Schedulers.newThread())
                        .blockingGet()))
            .takeUntil(response -> response.bodyAsJsonObject().getBoolean("next") == false)
            .map(response -> {
                if (response.statusCode() == 200) {
                    return response.bodyAsJsonObject().getJsonArray("results");
                }

            })
            .collect(JsonArray::new, JsonArray::addAll);
}

我们也确信这不是一个好方法……创建一个新线程然后将其阻止。任何人都可以提出正确的方法,谢谢。

更新:使用BehaviorSubject的非阻塞解决方案:

public Single<JsonArray> getData(Instant start, Instant end, Integer departmentId, Integer duration) {
        BehaviorSubject<Integer> pageControl = BehaviorSubject.createDefault(1);

        return pageControl
                .concatMapSingle(page -> webClient.getAbs(API_URL + "?page=" + page)
                        .rxSend()
                        .doOnSuccess(response -> {
                            if (response.bodyAsJsonObject().getBoolean("next")) {
                                pageControl.onNext(pageControl.getValue() + 1);
                            } else {
                                pageControl.onComplete();
                            }
                        })
                        .doOnError(pageControl::onError))
                .map(response -> {
                    if (response.statusCode() == 200) {
            return response.bodyAsJsonObject().getJsonArray("results");
                    }
                })
                .collect(JsonArray::new, JsonArray::addAll);
    } 

1 个答案:

答案 0 :(得分:1)

怀疑,blockingGet将阻止事件循环,这将破坏Vert.x golden rule

异步递归函数在这里会有所帮助:

public Single<JsonArray> getData() {
  return loadPage(0).collect(JsonArray::new, JsonArray::addAll);
}

public Observable<JsonArray> loadPage(int page) {
  return webClient.getAbs(API_URL + "?page=" + page)
    .expect(ResponsePredicate.SC_OK)
    .expect(ResponsePredicate.JSON)
    .as(BodyCodec.jsonObject())
    .rxSend()
    .flatMapObservable(response -> {
      JsonObject body = response.body();
      Observable<JsonArray> results = Observable.just(body.getJsonArray("results"));
      return !body.getBoolean("next") ? results : results.concatWith(loadPage(page + 1));
    });
}

使用这种功能,页面将总是一个接一个地加载,并且不会产生额外的请求。

请注意,为简化状态,内容类型和正文处理,上面的代码段使用了响应谓词正文编解码器