简体   繁体   English

依赖期货

[英]Dependent futures

Starting playing with Scala futures, I get stuck with dependent futures. 开始玩Scala期货,我陷入了依赖期货的困境。

Let's get a example. 我们来举个例子。 I search for places and get a Future[Seq[Place]] . 我搜索地点并获得Future[Seq[Place]] For each of theses places, I search for the closest subway stations (the service resurns a Future[List[Station]] ). 对于每个地方,我搜索最近的地铁站(该服务重新开始Future[List[Station]] )。

I would write this: 我会写这个:

Place.get()
.map { places =>
    places.map { place =>
        Station.closestFrom(place).map { stations =>
            SearchResult(place, stations)
        }
    }
}

That thing will make me get a Future[Seq[Future[SearchResult]]] ... which is... not what I would have expected. 那件事会让我得到一个Future[Seq[Future[SearchResult]]] ......这不是我所期待的。

What did I miss to get a Future[Seq[SearchResult]] ? 我错过了什么来获得Future[Seq[SearchResult]]

Thanks for all, 谢谢大家,

Alban 阿尔班

You are missing two Future concepts in your solution: flatMap and Future.sequence 您在解决方案中缺少两个Future概念: flatMapFuture.sequence

To explain each: 解释每个:

flatMap is like map except instead of giving it a function from future.map(A => B) you give it a function from future.flatMap(A => Future[B]) . flatMap就像map一样,除了从future.map(A => B)给它一个函数,你从future.flatMap(A => Future[B])给它一个函数future.flatMap(A => Future[B]) This way you can chain Futures together. 这样你就可以将期货连在一起了。

Future.sequence is a helper function that combines a list of futures to a future of a list: Seq[Future[A]] => Future[Seq[A]] Future.sequence是一个辅助函数,它将期货列表与列表的未来结合起来: Seq[Future[A]] => Future[Seq[A]]

Using these two features of the Future API we can change your answer to be: 使用Future API的这两个功能,我们可以将您的答案更改为:

Place.get().flatMap { places =>
    Future.sequence(places.map { place =>
        Station.closestFrom(place).map { stations =>
            SearchResult(place, stations)
        }
    })
}

Short version 简洁版本

Working with futures is generaly easier using for-comprehension rather than directly map/flatMap. 使用for-understand进行使用期望通常更容易,而不是直接映射/ flatMap。 In your situation it should look like this: 在你的情况下,它应该是这样的:

for {places        <- Place.get()
     searchResults <- Future.traverse(places)(place => for (stations <- Station.closestFrom(place))
                                                       yield SearchResult(place,stations)
                                              )
} yield searchResults

Detailed Version 详细版本

Future being a monad, it offers you several ways to chain your operations. Future是一个单子,它为您提供了几种连接您的运营方式。

  • If you want to apply an 'regular' function f : A => B to what's inside the box myfuture : Future[A] , indeed map is the way to get a Future[B] . 如果你想将一个'常规'函数f : A => B到框内的myfuture : Future[A] ,确实是map是获得Future[B] But in the present situation Station.closestFrom a does not give you a List[Stattion] but a Future[List[Station]] . 但是在目前情况下, Station.closestFrom a没有给你一个List[Stattion]而是一个Future[List[Station]]
  • If you want to apply a monadic operation h : A => Future[B] or chain several of them (here Places.get and Station.closestFrom ), flatMap is the way to go. 如果你想应用monadic操作h : A => Future[B]或链接其中几个(这里是Places.getStation.closestFrom ), flatMap就是你要走的路。 Apply h to a Future[A] gives you a Future[B] . h应用于Future[A]为您提供Future[B]
  • If you want to apply a monadic operation h : A => Future[B] to a collection like a places : Seq[A] , you should use Future.traverse : Seq[A] => (A => Future[B]) => Future[Seq[B]] . 如果你想将monadic操作h : A => Future[B]到类似places : Seq[A]的集合places : Seq[A] ,你应该使用Future.traverse : Seq[A] => (A => Future[B]) => Future[Seq[B]]

Furthermore, Scala's for-compresention is just syntactic sugar for flatMap/map so instead of writing complex code using those directly you can use a clean and clear for loop. 此外,Scala的for-compresention只是flatMap / map的语法糖,所以不用直接使用它们编写复杂的代码,你可以使用干净清晰的for循环。 The loop: 循环:

for { variable1 <- f1
      variable2 <- f2
} yield expression

is equivalent to (without optimisations) : 相当于(没有优化):

f1.flatMap( variable1 => f2.map(variable2 => expression))

Don't hesitate to use for-comprehension, it really helps. 不要犹豫使用for-understanding,它确实有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM