使用 Scala 和 Play 异步计算 Future Boolean

Evaluating a Future Boolean asynchronously using Scala and Play

我有一个 returns Play 控制器中的 Future[Boolean] 方法,我想使用异步对其进行评估,但我似乎无法编译它。 以下将起作用:

  def health = Action {
    logger.info("Endpoint method: health")
    val isHealthy = healthCheckService.checkDynamo()
    val b: Boolean = Await.result(isHealthy, scala.concurrent.duration.Duration(5, "seconds"))
    Ok(Json.toJson(HealthCheckResponse(b.toString)))
  }

但我不认为我想要 Await 在那里。所以我正在尝试这样的事情但没有成功:

 def health =
    Action.async {
      Future {
        logger.info("Endpoint method: health")


        healthCheckService.checkDynamo() match {
          case Future.successful(true)  => Ok(Json.toJson("false"))
          case false => Ok(Json.toJson("true"))
        }



        val r = healthCheckService.checkDynamo() match {
          case true  => Ok(Json.toJson("false"))
          case false => Ok(Json.toJson("true"))
        }

      }
    }

我什至不能让那些编译来测试它们。 有什么建议吗?

试试这个:

def health = Action.async {
  healthCheckService.checkDynamo().map {
    case true => Ok(Json.toJson("false"))
    case false => Ok(Json.toJson("true"))
  }
}

让 Play 处理引擎盖下等待您的事情。也就是说,Action.async 接受 FuturecheckDynamo() 已经 returns。您所要做的就是 map 得到适当的结果。

使用 Futures 时,您必须使用 mapflatMap 等组合子来表达最终值。例如:

Action.async {
  healthCheckService.checkDynamo()
    .map { result =>  // boolean
      HealthCheckResponse(result.toString)
    }
    .map(Json.toJson(_))
    .map(Ok(_))
}

(您可以将上面的 map 合并到一个 map 并在那里构建最终的 Ok 值;这或多或少是一个品味问题)

例如,如果您有两个要执行的异步调用并且 return 基于它们的结果的结果,您可以使用 flatMap,这可以很容易地用 for理解:

Action.async {
  for {
    result1 <- someService.someCall()
    result2 <- anotherService.anotherCall(result1.someProperty)
    finalResult = SomeFinalResultType(result1, result2)
  } yield Ok(Json.toJson(finalResult))
}

如果您不熟悉期货,您可能想阅读一些教程,其中解释了期货的性质、如何组合它们以及如何从中获得有用的结果,例如:http://hello-scala.com/920-scala-futures.html