如何从Scala中的Futures返回不同的结果,而不以嵌套的if语句结束

如何从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

我实际上在寻找一个更好的Scala构造,当它在不同的条件下从Future返回不同的结果时

比如说,在未来,我需要在返回成功结果之前进行某些验证。有两种方法可以做到这一点

方式一:

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的原因是失败案例通常也会返回异常。实际上,这就是我在实际代码中所做的。