我有一个方法可以创建类型为Future
的{{1}},然后从中创建合适的HTTP响应。
到目前为止,我已经尝试使用Futures API中的Vector
和transform
方法来实现这一点,主要是因为它们的自变量具有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)
答案 0 :(得分:2)
最简单的选择似乎是将其分为map
和recover
步骤:
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)))
)
)