0
votes

Could You please help me write it in a better way:

Future {
    Thread sleep 200
    5
} onComplete{
    case Success(e) => Future {
        doSomething(e)
        Thread sleep 200
        6
    } onComplete {
        case Success(e) =>
            Future {
                doSomething(e)
                Thread sleep 200
            } onComplete {
                case Success(_) => println("finished")
                case Failure(e) => e.printStackTrace()
            }
        case Failure(e) => e.printStackTrace()
    }

    case Failure(e) => e.printStackTrace()
}

Now the code looks bad, and if I added more futures this way it would become even worse... This is obviously an example to show the problem, so I would appreciate mentioning wider context.

@update If it is not clear enough, I will try to clarify. I have three futures, and want to execute the first, when it finishes execute the second, when it finishes - the third. The second future uses result of the first, and the third uses result of the second one. If one of futures fail, stack trace is printed and call sequence breaks. This is what I wanted to show in the code above, and I want to achieve it in better, non-nesting way, if possible.

@update 2 It would also be great if I would handle failure of each future separately

1
It isn't clear what you're trying to achievemfirry
ok, I updated the questionCom Piler

1 Answers

4
votes

Much like collections you can map() and flatMap() Futures (scaladoc) to combine them:

Future {
  Thread sleep 200
  5
}.map { result =>
  doSomething(result)
  Thread sleep 200
  6
}.map { result =>
  doSomething(result)
  Thread sleep 200
}.onComplete {
  case Success(_) => 
    // All steps completed successfully
    println("finished")
  case Failure(e) => 
    // This can be a failure from any of the steps
    e.printStackTrace()
}

map generates a result, whereas flatMap generates a Future instance.

Alternatively you can use for-comprehensions, which are just syntactic sugar for (flat)map calls.