将Scala列表[Either]评估为布尔值

时间:2018-12-19 16:10:54

标签: scala playframework

我正在使用scanamo查询dynamodb,而我要做的就是检查数据库是否确实存在。我并不真正担心我得到的记录,只是没有错误。对于查询部分,我正在使用它:

trait DynamoTestTrait extends AbstractDynamoConfig {  def test(): Future[List[Either[DynamoReadError, T]]] =    ScanamoAsync.exec(client)table.consistently.limit(1).scan())}
返回将来列表的

。我想先评估一下?列表中的项,如果不是读取错误,则返回true。

我认为这会起作用,但不会:

 val result = test() match {
      case r: DynamoReadError => Future.successful(false)
      case r: Registration    => Future.successful(true)
    }

我是scala的新手,所以在返回类型和事情上苦苦挣扎。这是一个Play api调用,因此我需要在某个时候评估这个布尔型的未来。像这样:

 def health = Action {
    val isHealthy = h.testDynamo()
    val b: Boolean = Await.result(isHealthy, scala.concurrent.duration.Duration(5, "seconds"))
    Ok(Json.toJson(TestResponse(b.toString)))
  }

我认为这也可能是错误的,因为我不想使用Await,但是我也无法使异步工作。 抱歉,我有点迷路。

当我尝试评估结果时,我只会收到关于未来的消息:

{
"status": 500,
"message": "Future(<not completed>) (of class scala.concurrent.impl.Promise$DefaultPromise)"
}

1 个答案:

答案 0 :(得分:2)

结果为Future,因此,如果不做类似Await.result的操作(如稍后所做),就无法测试结果。您可以做的就是将Future返回的结果修改为所需的结果。

您可以这样做:

test().map(_.headOption.forall(_.isRight))

这将返回Future[Boolean],您可以在您的Await.result通话中使用它。

这是它的工作方式:

  • mapFuture类型为List[Either[DynamoReadError, T]]的结果上调用一个函数,并返回一个新的Future来给出该函数调用的结果

  • _.headOption占据列表的开头并返回Option[Either[DynamoReadError, T]]。如果列表中有一个或多个元素,则为Some(...);如果列表为空,则为None

  • forall检查Option的内容,并返回对该选项的测试结果。如果OptionNone,则返回true

  • _.isRight测试值Either[...],如果值是true,则返回Right[...];如果值是false,则返回Left[...]

这可以完成您指定的操作,但是也许最好检查一下是否有任何结果失败,而不是仅检查第一个结果?如果是这样,它实际上会更简单:

test().map(_.forall(_.isRight))

这将检查List中的所有条目都是Right,并在找到Left时失败。

Play返回此值的问题是一个单独的问题,可能应该在一个单独的问题中。