我有一个方法可以创建一个Vector类型的Future,然后我想从它创建一个适当的HTTP响应。
到目前为止,我尝试使用来自Futures API的transform和transformWith方法来实现这一点,主要是因为它们的参数具有Try[T]签名,我可以区分成功和失败。
让我们假设这是生成Vector类型的Future的方法
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)
}发布于 2019-06-11 20:47:58
最简单的选择似乎是将其分为map和recover步骤:
val result = aCoupleOfFutures
.map(options => Created(json.Json.toJson(options)))
.recover{ case exc => BadRequest(exc.getMessage)}您说得对,似乎没有一个转换方法可以做您想要的事情--最接近的签名似乎是onComplete,但它返回Unit,因此不允许您生成返回值。也就是说,将两者分开并不一定是一件坏事,因为您经常希望抽象出所有控制器上的错误处理逻辑。
发布于 2019-06-16 19:40:23
在这里,折叠操作将非常有用-
def fold[U](fa: Throwable => U, fb: T => U): U这是一个终端操作,你想把所有的结果或异常都转换成Result。try/try/option上的折叠操作将处于任何状态的整个事物转换为类型U。
val result = aCoupleOfFutures
.transform(
tryResult =>
Success(
tryResult.fold(th => BadRequest(th.getMessage), options => Created(json.Json.toJson(options)))
)
)https://stackoverflow.com/questions/56543726
复制相似问题