【问题标题】:Scala Future: Transform Future[Vector[T]] to Future[Result]Scala Future:将 Future[Vector[T]] 转换为 Future[Result]
【发布时间】:2019-10-25 21:03:30
【问题描述】:

我有一个方法可以创建Vector 类型的Future,然后我想从中创建适当的 HTTP 响应。

到目前为止,我已经尝试使用 Futures API 中的 transformtransformWith 方法来实现这一点,主要是因为它们的参数具有 Try[T] 签名,我可以区分成功和失败。

假设这是产生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))

val foo:Future[Result] = aCoupleOfFutures.transform (
    options => Created(json.Json.toJson(options)),
    exc => exc
)

所以我的问题是:我可以有类似以下的东西吗:

val result:Future[Result] = aCoupleOfFutures. someKindOfTransform {
    case Success(options) => Created(json.Json.toJson(options))
    case Failure(e) => BadRequest(e.getMessage)
}

【问题讨论】:

    标签: scala playframework future


    【解决方案1】:

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

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

    你是对的,似乎没有一个单一的转换方法可以做你想做的事——最接近的签名似乎是onComplete,但它返回Unit,所以不允许你产生返回值。也就是说,将两者分开并不一定是坏事,因为您经常希望在所有控制器中抽象出错误处理逻辑。

    【讨论】:

    • 这似乎确实适用于恢复接收部分函数的唯一更正,recover(exc => BadRequest(exc.getMessage)) 似乎无效但.recover{case e:Throwable => BadRequest(e.getMessage)} 是。
    • 你说得对,是我的疏忽!现在已经修复了。
    【解决方案2】:

    折叠操作在这里会很有用-

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

    这是一个终端操作,您想将所有结果或异常转换为Result。对 try/either/option 的折叠操作会将处于任何状态的整个事物转换为 U 类型。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-30
      • 2016-05-04
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多