我正在使用scala dispatch(0.11.0)库向远程服务器发送HTTP GET请求。我想在执行请求之后的代码之前等待响应。
我的要求是:
val req = :/("myurl.com") <:< myheaders OK as.Response(identity)
如果我写:
val future = http(req)
future()
var res: String = null
future onComplete {
case Success(r) => res = r.getResponseBody
case _ => println("KO")
}
println(res)
我得到了空。 如果我写的话也是如此:
val future = http(req)
var res: String = null
while (!future.isCompleted) {
Thread.sleep(1000)
}
future onComplete {
case Success(r) => res = r.getResponseBody
case _ => println("KO")
}
println(res)
但是使用以下代码:
val future = http(req)
var res: String = null
future onComplete {
case Success(r) => res = r.getResponseBody
case _ => println("KO")
}
while (!future.isCompleted) {
Thread.sleep(1000)
}
println(res)
我得到了预期的回应。
有人理解这个吗? 在我看来,调用Thread.sleep不是一件好事,有人能给我一个关于我应该如何正确处理这个问题的提示吗?
编辑:@Randal Schulz感谢您的帮助,但正如您在评论中发表的那样,我无法验证您的答案。
由于我的问题是等待(并且什么也不做),直到我得到对HTTP GET请求的有效响应,我认为一种令人满意的方法是使用Await.result。我从代码中删除了副作用。我使用选项方法来处理Future失败(因为我只对成功感兴趣),并且我以经典方式处理超时异常。
我想我可以像小麦一样提到它,留在未来,但我需要更多练习......
答案 0 :(得分:3)
<强> TL; DR 强>
我可以为您提供在异步工作流程中工作的最佳建议是Future
中的Future
内容。
<强>答案强>
问题是你不知道Future
何时完成,所以如果你想使用异步过程,你将不得不以异步方式编写。您编写的代码永远不会在您创建的Future
上停止或阻塞,因此在创建Future
并将其移交给另一个线程的那一刻,当前线程可以自由地评估{{1}变量。
因此,将您正在做的大部分内容放在以下流程中:
res
请勿尝试像您一样通过副作用访问某些内容。
如果你真的聪明并且你有几个 myFuture map (func1) map (func2) map (func3) onComplete{
case Success(value) => println(value.getResponseBody)
case _ => println('KO')
}
,你可以组成它们:
Future
答案 1 :(得分:-2)
我终于设法用期货写了我想要的东西:
def loop(): Future[String] = {
val future = http(req).option
future flatMap ((x: Option[Response]) => x match {
case Some(rep) => rep.getResponseBody
case None => loop()
}
}
现在我可以使用此函数的结果而无需明确地等待响应。