2

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.

Alexandr
  • 349
  • 1
  • 4
  • 13

1 Answers1

9

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.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680