我实际上在寻找一个更好的Scala构造,当它在不同条件下返回Future的不同结果时。
可以说,在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)
但是我的方法存在问题,它会导致异常scala.runtime.NonLocalReturnControl。你可以在这个链接中找到解释:https://tpolecat.github.io/2014/05/09/return.html
这让我们留下了Way II。但是这个结构的问题在于它很快会变得丑陋,有更多的验证。
任何人都可以提出更好的表达方式吗?
如果这是这个问题的正确位置,请告诉我,或者需要以更好的方式表达这个问题。
TIA。
考虑将每个验证提取到单独的Future
中
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)