I use WSClient
to make rest requests. Each request return some Future
.
as result I need to make request 1 and get some data. Then I need to make request 2 with data from result of request 1. Then I need to make request 3 with data from result of request 2. and so on
in my code it's looks like
def wsChain(data: Data): Future[NewData] = {
getOne(data).flatMap(data2 => {
getTwo(data2).flatMap(data3 => {
getThree(data3).flatMap(data4 => {
getFour(data4).map(result => foo(result))
})
})
})
}
It's very primitive sample without any modification of responses and requests. but I think that even it is difficult to read.
I now about Await
for Future
, but it's anti-pattern
May be I can do this more pretty? Without N inner functions.
This is precisely the kind of situation that Scala's for
-comprehensions are designed to help. You can replace your code with the following:
def wsChain(data: Data): Future[NewData] = for {
data2 <- getOne(data)
data3 <- getTwo(data2)
data4 <- getThree(data3)
result <- getFour(data4)
} yield foo(result)
…and it will be desugared by the compiler to exactly the same thing. You can read more about for
-comprehensions here, but in short, any time you find yourself with a long chain of flatMap
calls (and maybe a map
at the end), you should consider rewriting them as a for
-comprehension, which makes your code more readable by collapsing the deep nesting.