如何从Scala中的Futures返回不同的结果,而不以嵌套的if语句结束
我实际上在寻找一个更好的Scala构造,当它在不同的条件下从Future返回不同的结果时 比如说,在未来,我需要在返回成功结果之前进行某些验证。有两种方法可以做到这一点 方式一:如何从Scala中的Futures返回不同的结果,而不以嵌套的if语句结束,scala,future,Scala,Future,我实际上在寻找一个更好的Scala构造,当它在不同的条件下从Future返回不同的结果时 比如说,在未来,我需要在返回成功结果之前进行某些验证。有两种方法可以做到这一点 方式一: Future { if(!validation1()) return Future.failed("Validation1 failed!") if(!validation2()) return Future.failed("Validation2 failed!") if(!validatio
Future {
if(!validation1()) return Future.failed("Validation1 failed!")
if(!validation2()) return Future.failed("Validation2 failed!")
if(!validation3()) return Future.failed("Validation3 failed!")
Future.successful()
}.flatMap(identity)
Future {
if(!validation1())
Future.failed("Validation1 failed!")
else {
if(!validation2())
Future.failed("Validation2 failed!")
else {
if(!validation3())
Future.failed("Validation3 failed!")
else {
Future.successful("Results")
}
}
}
}.flatMap(identity)
方式二:
Future {
if(!validation1()) return Future.failed("Validation1 failed!")
if(!validation2()) return Future.failed("Validation2 failed!")
if(!validation3()) return Future.failed("Validation3 failed!")
Future.successful()
}.flatMap(identity)
Future {
if(!validation1())
Future.failed("Validation1 failed!")
else {
if(!validation2())
Future.failed("Validation2 failed!")
else {
if(!validation3())
Future.failed("Validation3 failed!")
else {
Future.successful("Results")
}
}
}
}.flatMap(identity)
但是方式I有一个问题,它导致异常scala.runtime.NonLocalReturnControl。您可以在此链接中找到解释:
这就给我们留下了第二条道路。然而,这种构造的问题是,随着验证次数的增加,它很快就会变得丑陋
有人能提出更好的表达方式吗
请让我知道这是否是这个问题的正确位置,或者这个问题需要以更好的方式表达
TIA.考虑将每个验证提取到单独的
未来
def val1():Furure[String] =
if validation1() Future.failed("Validation1 failed") else Future.successful("Result")
def val2():Furure[String] =
if validation2() Future.failed("Validation2 failed") else Future.successful("Result")
def val3():Furure[String] =
if validation3() Future.failed("Validation3 failed") else Future.successful("Result")
然后使用flatMap
val1().flatMap(_ => val2()).flatMap(_ => val3())
还是用语法糖
for {
_ <- val1()
_ <- val2()
result <- val3()
} yield result
用于{
_那么:
def validation1(): (Boolean, String) // Tuple with e.g. (testResult, "Validation1 failed!")
def validation2(): (Boolean, String)
def validation3(): (Boolean, String)
val firstFound = Seq(validation1(), validation2(), validation3()).find(_._1)
if (firstFound.isEmpty) Success("Results") else Failure(firstFound.map{_._2}.get)
对于这类问题,这里绝对是正确的位置;)然而,这两个变体(即使它们有效)似乎都返回类似于Future[Future[String]]
。你真的想这样做吗?如果你不想这样做,也许你可以尝试调整你的示例,直到它们忠实地代表你希望在实际代码中实现的目标。我不确定我是否理解正确,但如果你验证某个表单,你通常希望返回所有失败验证的信息,而不仅仅是第一次验证你找到了。看起来你可能想使用。pure(fx)。flatMap(identity)=fx
对于每个fx:Future[X]
@AndreyTyukin我已经修复了返回Future[String]的代码。我在外部未来中返回Future.successful和Future.failed的原因是失败案例通常也会返回异常。实际上,这就是我在实际代码中所做的。