替代await.ready

时间:2016-12-12 13:07:29

标签: scala

我在Scala中有以下代码:

val status: Future[String] = Await.ready(Http(address OK as.String), 1 second)

我正在拨打http电话,我等了一秒钟的答案。

我被告知阻止使用Await.ready是不好的做法。

我很好奇我能用什么。

我可以用于理解吗?怎么样?

2 个答案:

答案 0 :(得分:3)

阻止异步操作通常很糟糕,否则,为什么要使它异步?

您可以使用Future[T]的各种实现,例如注册延续以在结果到达时调用。例如,假设您要将String结果解析为Foo对象。你会得到:

val result: Future[Foo] = Http(address OK as.String).map {
  s => parseJson[Foo](s)
}

请注意,在使用Future[T]时,除非您同步阻止,否则最终会将它们冒出执行的调用链。

理解可以达到同样的效果:

for {
 s <- Http(address OK as.String)
} yield (parseJson[Foo](s))

答案 1 :(得分:2)

使用Await.ready不是一个好习惯,因为它阻止了。在大多数情况下,您可以撰写和转换期货以达到预期的结果。

但是你可以在绝对必要时使用阻止。以下是关于阻止及其后果的答案When to and when not use blocking

非阻止等待

def afterSomeTime(code: => Unit)(duration: FiniteDuration): Unit = {
  someActorSystem.scheduler.scheduleOnce(duration) {
    code
  }
} 

上面的函数会在给定的持续时间后调用代码,你可以使用任何其他的定时器实现代替Akka调度程序

case class TimeoutException(msg: String) extends Exception(msg)

def timeout[T](future: => Future[T])(duration: FiniteDuration)(implicit ec: ExecutionContext): Future[T] = {

  val promise = Promise[T]()
  future.onComplete(promise tryComplete)

  afterSomeTime {
    promise tryFailure TimeoutException(s"Future timeout after ${duration.toString()}")
  }(duration)

  promise.future
}