This is a theoretical question. I have a service I can call to do a job, but that service might not do all of it, and thus I will need to call a second one to finish it.
I was wondering if there is a way to do something similar to this without Await.result the result within the map function:
val myFirstFuture = asyncRequestA()
myFirstFuture.map(result => {
result match {
case isWhatIExpected => result
case isNot => Await.result(asyncRequestB(), someDuration)
}
})
I would like to "merge" the future given by asyncRequestB() into myFirstFuture without using the Await function to get the result.
Any ideas?
Future is a monad. And the standard way of working with monads in Scala is using a "for comprehension":
for {
firstResult <- firstFuture
secondResult <- firstResult match {
case isWhatIExpected => Future.successful( firstResult )
case isNot => asyncRequestB()
}
}
yield secondResult
In Scala "for comprehension" is a syntactic sugar for a series of flatMap, map and filter method applications and under the hood the compiler will expand this comprehension into the same thing as in Regis' answer.
Although in this case you might not exactly see the benefit from using a "for comprehension" syntax, when you drop in another Future and when things start getting trickier, it will come to shine. What "for comprehension" basically does is it flattens the otherwise many levels of nesting of those three method applications.
Secondly, there's also a way you could optimize Regis' solution syntactically, by utilizing "partial functions":
myFirstFuture.flatMap{
case r if isWhatIExpected( r ) => Future.succesful( r )
case r if isNot( r ) => asyncRequestB()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With