RXjava复杂的异步任务

时间:2017-10-03 09:37:48

标签: rx-java2

我正在尝试使用异步rxjava流来处理复杂的任务。

我获取指标列表和城市列表并获取其值(日期和值列表)。每个度量标准都存储在不同的数据库中,因此需要进行大量的HTTP调用。

结果顺序意味着什么,所以我想:

以异步方式运行所有指标。 对于我想要异步运行在所有城市的每个指标。 对于每个城市和指标,我想创建一个HTTP调用来获取数据。

最终答案应如下所示:

"result": {
  "metric1": [
    {
      "cityId": 8,
      "values": [
        {
          "date": "2017-09-26T10:49:49",
          "value": 445
        },
        {
          "date": "2017-09-27T10:49:49",
          "value": 341
        }
      ]
    },
    {
      "cityId": 9,
      "values": [
        {
          "date": "2017-09-26T10:49:49",
          "value": 445
        },
        {
          "date": "2017-09-27T10:49:49",
          "value": 341
        }
      ]
    }
  ],
  "metric2": [
    {
      "cityId": 8,
      "values": [
        {
          "date": "2017-09-26T10:49:49",
          "value": 445
        },
        {
          "date": "2017-09-27T10:49:49",
          "value": 341
        }
      ]
    },
    {
      "cityId": 9,
      "values": [
        {
          "date": "2017-09-26T10:49:49",
          "value": 445
        },
        {
          "date": "2017-09-27T10:49:49",
          "value": 341
        }
      ]
    }
  ]
}
  }
}

我怎样才能做到这一点?迷失了所有的观察者。哪个应该是阻塞,哪个应该返回一个真正的值?

编辑:添加代码示例 以下是我到目前为止的情况:

    1. for each metric (parallel I guess):


         Observable.from(request.getMetrics())
                            .subscribe(metric -> {
                                List metricDataList = getMetricData(metric, citiesList);
                                result.put(metric.getName(), metricDataList);
                            });

                return ImmutableMap.of("result",   result);


    2. Get metric data (according to cities):

        final List<Map<String,Object>> result = new ArrayList<>();
                Observable.from(citiesList).subscribe(city ->
                        result.add(ImmutableMap.of(
                                "id", city.getId(),
                                "name", city.getName(),
                                "value", getMetricValues(metricType, city.getId())
                                     .toBlocking()
                                     .firstOrDefault(new ArrayList<>()))));

                return result;

3. According to metric I decide which service to invoke:
private Observable<List<AggregatedObject>> getMetricValues(AggregationMetricType metric, Integer cityId) {

        switch (metric) {
            case METRIC_1:        return fetchMetric1(city);
            case METRIC_2:        return fetchMetric2(city);
        }

        return Observable.empty();
    }


4. Invoke the service:

public Observable<List<AggregatedObject>> fetchMetric1(Integer city) {
        return Observable.just(httpClient.getData(city)
                .map(this::transformCountResult)
                .onErrorResumeNext(err -> Observable.from(new ArrayList<>()));
    }

5. Transform the received data:
protected List<AggregatedObject> transformCountResult(JsonNode jsonNode) {
        ...
    }

虽然我不确定我是否已经正确地实现了阻塞和并发性,但它仍在工作。

请帮助。

此致 IDO

1 个答案:

答案 0 :(得分:0)

在您调用“2)获取指标数据”的步骤中,您可以重构为

    final List<Map<String,Object>> result = new ArrayList<>();
    Observable.from(citiesList)
     .flatMap(city -> getMetricValues(metricType, city.getId())
                       .firstOrDefault(new ArrayList<>())
                       .map( metric -> ImmutableMap.of(
                                      "id", city.getId(),
                                      "name", city.getName(),
                                      "value", metric) ) )
     .toList()
     .toBlocking()
     .subscribe( resultList -> result = resultList );

toBlocking()移到处理之外意味着单个请求将以更加平行的方式发生。