我有三个功能。
myFunc1:
def myFunc1(cluster: String, consumer: String) = Action.async { implicit request =>
kafkaManager.getConsumerIdentity(cluster, consumer) map { errorOrT =>
errorOrT.fold(
error => BadRequest(Json.obj("msg" -> error.msg)),
T=> {
Ok(Json.obj("summary" -> getSummary(cluster, consumer, T.Map.keys)))
})
}
getSummary:
def getSummary(cluster: String, consumer: String, myMap: Iterable[String]) = {
var topics: Map[String, JsObject] = Map()
myMap.map { key =>
topicSummary(cluster, consumer, x).map(r => {
r.fold(l => {}, value => {
topics += key -> value
})
})
}
topics
}
和topicSummary:
def topicSummary(cluster: String, consumer: String, topic: String) = {
kafkaManager.getConsumedTopicState(cluster, consumer, topic).map { errorOrTopicSummary =>
errorOrTopicSummary.map(
topicSummary => {
Json.obj("totalLag" -> topicSummary.totalLag.getOrElse(None).toString(), "percentageCovered" -> topicSummary.percentageCovered)
})
}
}
结果是:
{"summary":()}
问题是getSummary没有等到结果。 我很想听听如何解决它的建议
答案 0 :(得分:1)
很难准确说出发生了什么,因为你没有在你的函数上放置显式的返回类型。假设所有Kafka调用都是异步的,出现的情况是topicSummary
返回Future[JsObject]
,但调用它的getSummary
不会等待它的结果,但立即返回(空)主题地图。
当您与期货打交道时,您需要:
Await
未来实现其结果(不推荐)您可以通过异步实现getSummary
来解决此问题,这看起来像这样:
myFunc1:
def myFunc1(cluster: String, consumer: String) = Action.async { implicit request =>
// NB: Since we're dealing with a Future within a Future, we
// use flatMap to combine them
kafkaManager.getConsumerIdentity(cluster, consumer).flatMap { errorOrT =>
errorOrT.fold(
error =>
// In the case of an error, return a no-op Future with .successful
Future.successful(BadRequest(Json.obj("msg" -> error.msg))),
// Otherwise, map over the results of get summary
T => getSummary(cluster, consumer, T.Map.keys).map { topics =>
Ok(Json.obj("summary" -> topics))
}
)
}
}
getSummary(近似代码):
def getSummary(cluster: String, consumer: String, myMap: Iterable[String]): Future[Map[String, JsObject]] = {
// For each key you expect a Future[JsObject], which you want to
// transform into a tuple of key/object
val topicKeys: List[Future[(String, JsObject)]] = myMap.toList.map { key =>
topicSummary(cluster, consumer, key)
// Map the future optional value with its key, defaulting
// to an empty object
.map(topicsOpt => key -> topicsOpt.getOrElse(Json.obj()))
// OPTIONAL: handle any error with an empty object
.recover {
case _ => key -> Json.obj()
}
}
// Finally, use Future.fold to turn a list of futures into a
// single Future sequence, then combine the (String, JsObject)
// tuples into a map
Future.fold(topicKeys)(Map.empty[String, JsObject])(_ + _)
}
当处理期货以明确预期的回报类型时,这是非常有用的,至少在试图了解中间状态时。如果你最终得到太多嵌套地图和flatMaps,请使用for
推理来调查以使事情看起来更清晰,但这是另一个问题。