Scala Pattern: For Comprehension that Yields a Future[A]

橙三吉。 提交于 2019-12-12 04:24:59

问题


What is the pattern used in Scala to deal with the scenario:

You have a bunch of futures (they can be whatever, but for the sake of example...)

val aF = Future { true }
val bF = Future { Option(3) }
val cF = Future { myObject }

and you have some function that returns a future

def fooF: Future[SomeObject]

I want to do something like:

for {
    a <- aF
    b <- bF
    c <- cF
} yield {
    if (a) {
        // do stuff with b & c
        fooF
    } else {
        Future.successful(SomeObject)
    }
}

I want to return a value of Future[SomeObject], but I call fooF inside of the yield statement, I will get a Future[Future[SomeObject]]


回答1:


Here is another solution :

def doStuffWith(a: A, b: B, c: C): Future[SomeObject] = if (a) {
  // do stuff with b & c
  fooF
} else Future.successful(SomeObject)

for {
  a <- aF
  b <- bF
  c <- cF
  d <- doStuffWith(a, b, c)
} yield d

As discussed in @laughedelic answer, this is a subjective view, but I believe this way to be more readable, and maintainable (taking out the function always to unit test it, for instance).




回答2:


  • In Scala 2.12 Future has a flatten method:

    Creates a new future with one level of nesting flattened, this method is equivalent to flatMap(identity).

    So you can write for { ... } yield { ... } flatten.

  • In Scala <2.12 you can achieve the same with flatMap(identity) (as mentioned above)


An alternative solution is to use flatMap instead of for-comprehension:

aF.flatMap { a =>
  if (a) {
    (bF zip cF).flatMap { (b, c) =>
      // do stuff with b & c
      fooF
    }
  } else 
    Future.successful(SomeObject)
  }
}


来源:https://stackoverflow.com/questions/40599279/scala-pattern-for-comprehension-that-yields-a-futurea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!