How to return different results from futures in Scala without ending in nested if statements

I'm really looking for a better Scala design when it comes to returning different results from Future under different conditions.

Let's say, inside the future, I need to do some checks before returning a successful result. There are two ways to do this.

Method I:

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)

Method II:

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)

But there is a problem with Way I , this leads to scala.runtime.NonLocalReturnControl exception. You can find an explanation at this link: https://tpolecat.imtqy.com/2014/05/09/return.html

What leaves us with Way II . The problem with this design is that it soon becomes ugly with lots of checks.

- ?

, , , .

.

+4
2

, 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
+4

:

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)
0

Source: https://habr.com/ru/post/1694294/


All Articles