我有3种方法:a,b和c。 方法a有一些逻辑,它调用方法b。 方法b进行api调用,返回Future [String]。 如果方法b的返回值是某个值,则调用方法c。 方法c进行另一个api调用,返回另一个Future [String]。
def a: String = Action { request =>
val x = b("hello")
x
}
def b(y: String): Future[String] = {
val x = ws.url(url).post(y).map { response =>
val value = response.body
val z = if (response.body === "hi") response.body else c(response.body)
z
}
x
}
def c(z: String): Future[String] = {
val x = ws.url(url).post(z).map { response =>
response.body
}
x
}
类似上面的代码。最终,我想将所有内容解析为json对象,但是我无法将Futures作为常规字符串获取。我是scala的新手,请多多投入。
答案 0 :(得分:0)
您会想要这样的东西:
def a: Action[AnyContent] = Action.async { _ =>
b("hello").map(s => Ok(s))
}
def b(y: String): Future[String] = {
ws.url(url).post(y).flatMap { response =>
if (response.body == "hi") Future.successful(response.body) else c(response.body)
}
}
def c(z: String): Future[String] = {
ws.url(url).post(z).map { response =>
response.body
}
}
几件事。
1)方法a
的类型将是Action[AnyContent]
,因为您正在创建播放Action
。人们通常会忽略操作方法的类型,而让编译器将其弄清楚,这很常见。请注意,如果您的操作更为复杂(例如,它读取JSON请求正文),则其类型可能为Action[something_else]
(例如,如果您使用Play Json,则为Action[JsValue]
)。
2)因为b
返回了将来,所以您需要使用Action
创建Action.async
来使用Request => Future[Response]
类型的函数创建Action.apply
(在调用{{1 }},其功能类型为Request => Response
。
3)在A
中,您需要将map
中的String
到Future
;我使用Response
(即HTTP 200)来执行此操作,尽管您当然可以使用任何合适的方法。
4)在Ok
中,b
是您的朋友,因为flatMap
返回一个c
,因此当您使用{时,最终会得到一个Future[String]
{1}} ... Future[Future[String]]
将其展平为map
。
5)您需要将flatMap
语句的第一个分支包装在Future[String]
中,以使两个分支都返回相同的类型if
。 Future.successful
只是建立一个已经完成的Future[String]
。
6)最后,您不需要声明值Future.successful
,Future
和x
;每个表达式都解析为它的值,这实际上使事情变得井井有条。