Scala Future:将Future [Vector [T]]转换为Future [Result]

时间:2019-06-11 12:26:55

标签: scala playframework future

我有一个方法可以创建类型为Future的{​​{1}},然后从中创建合适的HTTP响应。

到目前为止,我已经尝试使用Futures API中的Vectortransform方法来实现这一点,主要是因为它们的自变量具有transformWith签名,我可以区分成功与否。失败。

我们假设这是产生类型Try[T]的{​​{1}}的方法

Future

使用这种方法,您会注意到Vector结构的重复使用

def aCoupleOfFutures: Future[Vector[String]] = ???

使用这种方法,可以注意到Try嵌套的重复使用。

val foo:Future[Result] = aCoupleOfFutures.transform {
    case Success(strings) => Try(Created(json.Json.toJson(strings)))
    case Failure(e) => Try(BadRequest(e.getMessage))
}

使用这种方法,当服务产生异常时,我无法返回所需的Future.successful。由于重载的val foo:Future[Result] = aCoupleOfFutures.transformWith { case Success(strings) => Future.successful(Created(json.Json.toJson(strings))) case Failure(e) => Future.successful(BadRequest(e.getMessage)) } 方法的签名是(BadRequest

transform

所以我的问题是:我可以输入以下内容吗?

def transform[S](s: T => S, f: Throwable => Throwable)

2 个答案:

答案 0 :(得分:2)

最简单的选择似乎是将其分为maprecover步骤:

val result = aCoupleOfFutures
  .map(options => Created(json.Json.toJson(options)))
  .recover{ case exc => BadRequest(exc.getMessage)}

您是对的,似乎没有单一的转换方法可以执行您想要的操作-最接近的签名方式似乎是onComplete,但返回的是Unit,因此不允许您产生一个返回值。就是说,将两者分开不一定是一件坏事,因为您经常想抽象出所有控制器上的错误处理逻辑。

答案 1 :(得分:1)

这里的折叠操作将很有用-

def fold[U](fa: Throwable => U, fb: T => U): U

这是一个终端操作,您要将所有结果或异常都转换为Result。在try /任选/选项上的折叠操作将处于任意状态的整个事物转换为类型U

val result = aCoupleOfFutures
  .transform(
    tryResult =>
      Success(
        tryResult.fold(th => BadRequest(th.getMessage), options => Created(json.Json.toJson(options)))
      )
  )