Scala 什么';发送一个简单的HTTP请求并用Akka获得响应的最佳实践是什么?
我试着这样编写代码:Scala 什么';发送一个简单的HTTP请求并用Akka获得响应的最佳实践是什么?,scala,akka,akka-http,Scala,Akka,Akka Http,我试着这样编写代码: val requestUri : Uri = baseUri.withQuery(Uri.Query("aid" -> av))//av is a query parameter val responseFuture: Future[HttpResponse] = Http(system).singleRequest(HttpRequest(GET, uri = requestUri)) val response = Await.result(responseFutu
val requestUri : Uri = baseUri.withQuery(Uri.Query("aid" -> av))//av is a query parameter
val responseFuture: Future[HttpResponse] =
Http(system).singleRequest(HttpRequest(GET, uri = requestUri))
val response = Await.result(responseFuture, Duration.Inf)
我想我得到了正确的回答,但是我怎样才能得到回答的内容呢?这样做的最佳实践是什么?像这样使用
Future
正确吗?一般来说,在Future
上使用wait
是不好的形式。这通常是不必要的,但如果你对未来不熟悉,“感觉”是正确的方法
一旦结果成为未来,您可以将计算留在未来的“内部”,并在原始值的基础上添加更多功能
直接处理你的问题,你可以使用未来的操作符,而不是等待“得到响应的内容”(参见Frederic A.的答案,为什么要在下一个解决方案之前考虑流):< /P> 这一系列操作也可以通过以下方式完成:
val responseBody : Future[ByteString] =
for {
entity <- responseFuture.entity
strict <- entity.toStrict(10 seconds)
body <- strict.data
} yield body
再次请注意,我们能够通过testring将HttpResponse
转换为HttpResponse
,并在不使用wait的情况下打印结果。相反,我们使用map
、flatMap
和foreach
来完成任务
我第一次使用Futures时使用的一个心理技巧是将未来想象成一种特殊的数组。您不能从数组中选择元素,Wait就是这样做的,但是当您想要对元素进行操作时,您可以在特殊数组中使用map和flatMap。一般来说,在
将来的上使用Wait
是不好的。这通常是不必要的,但如果你对未来不熟悉,“感觉”是正确的方法
一旦结果成为未来,您可以将计算留在未来的“内部”,并在原始值的基础上添加更多功能
直接处理你的问题,你可以使用未来的操作符,而不是等待“得到响应的内容”(参见Frederic A.的答案,为什么要在下一个解决方案之前考虑流):< /P>
这一系列操作也可以通过以下方式完成:
val responseBody : Future[ByteString] =
for {
entity <- responseFuture.entity
strict <- entity.toStrict(10 seconds)
body <- strict.data
} yield body
再次请注意,我们能够通过testring将HttpResponse
转换为HttpResponse
,并在不使用wait的情况下打印结果。相反,我们使用map
、flatMap
和foreach
来完成任务
我第一次使用Futures时使用的一个心理技巧是将未来想象成一种特殊的数组。您不能从数组中选择元素,这正是Wait所做的,但您可以在需要对元素进行操作时在特殊数组中使用map和flatMap。Akka http基于Akka streams,原因很多,可以帮助您理解这里发生了什么:如果运行代码的计算机只有64Gb的RAM,而HTTP响应的大小是784Tb,也就是说,远远超过RAM+交换的容量,该怎么办?流式解决方案是解决这一问题的唯一方法,而这正是akka http擅长的
因此,在您的例子中,当responseFuture
完成时,基本上意味着只有http响应的头可用,而不是内容可用。请记住,内容可能很大,下载需要几个小时,但您仍然可以期望响应未来
在不到一秒钟内完成
您所称的响应内容称为http实体。Akka http将其作为流提供,但对于像您这样的情况,您可以调用实体上的.toStrict
,将其作为字节数组(未来的)而不是流
最后,使用wait
几乎永远都不对。你应该在未来完成时采取行动,或者使用.onComplete
/。onSuccess
/。onFailure
,或者将结果映射到某个东西,可能使用。map
和/或与其他期货结合使用。flatMap
Akka http基于很多原因基于Akka流,可以帮助您理解这里发生了什么:如果运行代码的计算机只有64Gb的RAM,而HTTP响应的大小是784Tb,也就是说,远远超过RAM+交换的容量,该怎么办?流式解决方案是解决这一问题的唯一方法,而这正是akka http擅长的
因此,在您的例子中,当responseFuture
完成时,基本上意味着只有http响应的头可用,而不是内容可用。请记住,内容可能很大,下载需要几个小时,但您仍然可以期望响应未来
在不到一秒钟内完成
您所称的响应内容称为http实体。Akka http将其作为流提供,但对于像您这样的情况,您可以调用实体上的.toStrict
,将其作为字节数组(未来的)而不是流
最后,使用wait
几乎永远都不对。你应该在未来完成时采取行动,或者使用.onComplete
/.onSuccess
/.onFailure
或者将结果映射到某个东西,可能使用.map
和/或.flatMap
与其他未来结合使用。谢谢你的帮助!但是代码中有一个小错误:toStrict
只接受FiniteDuration
作为参数,因此Duration.Inf
将导致类型不匹配。将其更改为1秒
并导入import scala.concurrent.duration.\u
将修复它。我还有一个问题:设置超时的最佳做法是什么?@HuangYuheng欢迎您。我在有限的时间内修改了答案。一般来说,没有超时的“最佳实践”。我通常拍摄一段时间,99.9%的时间会检索到身体,这取决于您查询的服务。祝你黑客愉快。谢谢你的帮助!但是有一个
responseBody foreach { body =>
println s"body: ${body.utf8String}"
}