我试图从Vertex AsyncSqlClient中收集Observable<ResultSet>
到HashMap。
Map<String, Integer> map = Maps.newHashMap();
asyncSQLClient
.getConnectionObservable()
.flatMap(sqlConnection -> sqlConnection.queryObservable("select a, b from table")
.doOnCompleted(sqlConnection::close)
.doOnError(throwable -> log.error("Error while querying.", throwable)))
.flatMap(resultSet -> Observable.from(resultSet.getRows()))
.toBlocking()
.forEach(row -> map.put(row.getString("a"), row.getInteger("b")));
但这似乎永远阻止了。
在搜索了一段时间后没有任何结果,你介意借给我一只手吗?
答案 0 :(得分:1)
正如@Phoenix Wang评论的那样,forEach()
方法will block until Observable will completes。意味着如果你有Observable
发出无限项,或者你有一个Observable错误地发出onCompleted
来表示Observable完成,它将永远阻止。
这可能是由getConnectionObservable()
方法实施引起的,如果它创建了自定义Observable
,例如使用Observable.create()
,则必须先致电onCompleted()
物品被发出。
无论如何,你应该知道toBlocking()
会阻塞和等待,这可能不适合生产代码(因为它打破了反应的所有目的),你可以达到同样的目的reduce()
:
asyncSQLClient
.getConnectionObservable()
.flatMap(sqlConnection -> sqlConnection.queryObservable("select a, b from table")
.doOnCompleted(sqlConnection::close)
.doOnError(throwable -> log.error("Error while querying.", throwable)))
.flatMap(resultSet -> Observable.from(resultSet.getRows()))
.reduce(Maps.newHashMap(), (map, o) -> map.put(row.getString("a"), row.getInteger("b")))
.subscribe(map -> {
//do something with map
}
);
请注意,您仍然需要解决onCompleted
问题,因为reduce也会期望Observable
完成,并会在源Observable
完成时发出信号项。
其他选项是使用scan()
(只需用扫描替换reduce),使用扫描,您将获得使用源Observable
发出的每个项目的排放,这意味着您将累积项目以便随时间映射。