依赖期货

时间:2015-05-24 13:10:12

标签: scala playframework-2.0 future

开始玩Scala期货,我陷入了依赖期货的困境。

让我们举个例子。我搜索地点并获得Future[Seq[Place]]。对于每个地方,我搜索最近的地铁站(服务重新发现Future[List[Station]])。

我会这样写:

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

那件事会让我得到Future[Seq[Future[SearchResult]]] ......这不是我所期望的。

我错过了Future[Seq[SearchResult]]

谢谢大家,

阿尔

2 个答案:

答案 0 :(得分:6)

您的解决方案中缺少两个Future概念:flatMapFuture.sequence

解释每一个:

flatMapmap类似,但不是从future.map(A => B)给它一个函数,而是从future.flatMap(A => Future[B])给它一个函数。通过这种方式,您可以将期货连在一起。

Future.sequence是一个帮助函数,它将未来列表与列表的未来结合起来:Seq[Future[A]] => Future[Seq[A]]

使用Future API的这两个功能,我们可以将您的答案更改为:

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

答案 1 :(得分:2)

短版

使用for-understanding进行使用期望通常比使用for-understandnce更容易,而不是直接映射/ flatMap。在你的情况下它应该是这样的:

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

详细版本

Future是一个monad,它为您提供了几种连接操作的方法。

  • 如果您想申请&#39;常规&#39;函数f : A => Bmyfuture : Future[A]框内的内容,确实是map是获得Future[B]的方法。但在目前的情况下,Station.closestFrom a不会为您提供List[Stattion],而是Future[List[Station]]
  • 如果您想应用monadic操作h : A => Future[B]或链接其中的一些(Places.getStation.closestFrom),flatMap就可以了。将h应用于Future[A]会为您提供Future[B]
  • 如果您想将monadic操作h : A => Future[B]应用于places : Seq[A]这样的集合,则应使用Future.traverse : Seq[A] => (A => Future[B]) => Future[Seq[B]]

此外,Scala的for-compresention只是flatMap / map的语法糖,所以不用直接使用它们编写复杂的代码,你可以使用干净清晰的for循环。循环:

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

相当于(没有优化):

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

不要犹豫使用理解,这确实有帮助。