【问题标题】:Scala Play Future[Response] always emptyScala Play Future[Response] 始终为空
【发布时间】:2016-05-09 10:28:13
【问题描述】:

Future[Response].value:Option[Try[Response]] 始终为空。我误解了期货吗?我需要将其包装在onSuccess 中吗?但是它不会返回一个字符串,而是一个单元?

@tailrec private def initConnection: String =
  {
    val response: Future[Response] = initHeaders(WS.url(url)).post(authBody)
    val retry: Boolean = {
      response.value.isEmpty || response.value.get.isFailure || response.value.get.get.header("ConnectionID").isEmpty
    }

    if (!retry) return response.value.get.get.header("ConnectionID").get
    else initConnection
  }

【问题讨论】:

    标签: scala playframework playframework-2.0 future


    【解决方案1】:

    Future#value 不会阻止未来。如果调用value的时候future已经完成,你会得到Some(_),否则就是None。所以你只看到None,因为你在发送请求后立即检查value,但它还没有完成。您可以使用collectrecoverWith 等未来的组合子来实现重试功能并返回Future[String] 而不是String。如果你以后真的需要这个值,你将不得不Await.result未来。

    import scala.util.control.NonFatal
    import scala.concurrent.Await
    
    private def initConnectionFuture: Future[String] =
      initHeaders(WS.url(url)).post(authBody).collect {
        case response if response.header("ConnectionID").isDefined =>
          response.header("ConnectionID").get
      }.recoverWith {
        case NonFatal(_) => initConnectionFuture
      }
    
    private def initConnection: String =
      Await.result(initConnectionFuture, 5 seconds) // or any other acceptable timeout
    

    除了超时,您可能还想限制重试次数,例如

    private def initConnectionFuture(retries: Int = 5): Future[String] =
      initHeaders(WS.url(url)).post(authBody).collect {
        case response if response.header("ConnectionID").isDefined =>
          response.header("ConnectionID").get
      }.recoverWith {
        case NonFatal(_) if retries > 0 => initConnectionFuture(retries - 1)
      }
    

    【讨论】:

    • 谢谢,我以为它会异步执行,直到需要该值,此时它会自动阻塞。
    • 下列说法正确吗? “对 Future 进行的并发优化是在编译时完成的。我之前的假设需要运行时优化。”
    • 根据设计,Future 上的任何方法都不会阻塞。阻塞的唯一调用是 Await.result,这在 Future 上没有定义。
    • 我不知道 Future 有任何特殊的编译器优化。
    • 为什么在使用recoverWith 时会删除@tailrec? (甚至编译器都建议我删除注释)如果我不限制重试次数,无限递归时我们不会有潜在的堆栈溢出吗? Scala 是否自动优化以在recoverWith 上重用堆栈?还是没有优化,因此需要限制重试次数?
    猜你喜欢
    • 2013-01-24
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2016-05-04
    • 2019-10-25
    • 2021-08-27
    • 1970-01-01
    相关资源
    最近更新 更多