我应该如何等待Scala调度(0.11.0)HTTP获取请求要完成



我正在使用Scala dispatch(0.11.0)库将HTTP获取请求发送到远程服务器。我想在执行遵循请求的代码之前等待响应。

我的要求是:

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)

我得到了预期的响应。

有人理解这一点吗?在我看来,调用线程。睡觉不是一件好事,有人可以暗示我应该如何正确处理这个问题吗?

编辑:@randal Schulz谢谢您的帮助,但是当您在评论中发布时,我无法验证您的答案。

由于我的问题是等待(不做其他),直到我对HTTP获取请求做出有效响应,我认为一种令人满意的方法是使用等待。我从代码中删除了副作用。我使用选项方法来处理未来的失败(因为我只对成功感兴趣),并且我处理了经典之路的超时例外。

我认为我可以像提到小麦一样做到这一点,以后会留下来,但我需要更多的练习...

tl; dr

我可以为您提供在异步工作流程中工作的最佳建议是,进入Future的方法保留在Future中。

答案

问题是您不知道Future何时完成,因此,如果要使用异步过程,则必须以异步方式写入。您已经编写的代码永远不会停止或在Future上创建的块,因此它创建Future并将其交给另一个线程时,当前线程可以免费评估res变量。

因此,将您所做的大部分内容都放在如下:

 myFuture map (func1) map (func2) map (func3) onComplete{
   case Success(value) => println(value.getResponseBody)
   case _ => println('KO')
 }

不要像您一样尝试通过副作用访问某些东西。

如果您真的很聪明,并且有几个Future,则可以组成它们:

val f1 = myFuture map(func1)
val f2 = myOtherFuture map(func2) map (func3)
val f3 = for{
  v1 <- f1
  v2 <- f2
} yield functionTakingBoth(v1, v2)
f3 onComplete{
  //and do stuff here
}

我终于设法写了我想要的东西:

def loop(): Future[String] = {
    val future = http(req).option
    future flatMap ((x: Option[Response]) => x match {
        case Some(rep) => rep.getResponseBody
        case None => loop()
    }
}

现在,我可以使用此功能的结果,而无需明确等待响应的到来。

最新更新