如何在scala中转换Option[Future[T]]为Future[Option[T]]?
我想用它:
val customerAddresses = for {
a <- addressDAO.insert(ca.address) // Future[Address]
ia <- ca.invoiceAddress.map(addressDAO.insert) // Option[Future[Address]]
} yield (a, ia) // Invalid value have to be two futures
Run Code Online (Sandbox Code Playgroud)
这里签名插入方法
def insert(address: Address): Future[Address]
Run Code Online (Sandbox Code Playgroud)
ca 是CustomerData
case class CustomerData(address: Address, invoiceAddress: Option[Address])
Run Code Online (Sandbox Code Playgroud)
Kev*_*ith 26
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
def f[A](x: Option[Future[A]])(implicit ec: ExecutionContext): Future[Option[A]] =
x match {
case Some(f) => f.map(Some(_))
case None => Future.successful(None)
}
Run Code Online (Sandbox Code Playgroud)
例子:
scala> f[Int](Some(Future.successful(42)))
res3: scala.concurrent.Future[Option[Int]] = Success(Some(42))
scala> f[Int](None)
res4: scala.concurrent.Future[Option[Int]] = scala.concurrent.impl.Promise$KeptPromise@c88a337
Run Code Online (Sandbox Code Playgroud)
gun*_*gun 12
如果您的应用程序中有猫作为依赖项,那么最好的方法是使用 traverse
import cats._
import cats.implicits._
val customerAddresses = for {
a <- addressDAO.insert(ca.address) // Future[Address]
ia <- ca.invoiceAddress.traverse(addressDAO.insert) // Future[Option[Address]]
} yield (a, ia)
Run Code Online (Sandbox Code Playgroud)
小智 9
这是另一个解决方案:
def swap[T](o: Option[Future[T]]): Future[Option[T]] =
o.map(_.map(Some(_))).getOrElse(Future.successful(None))
Run Code Online (Sandbox Code Playgroud)
诀窍是转换Option[Future[T]]为Option[Future[Option[T]]]which 很容易,然后从中提取值Option。
小智 8
标准库确实提供了在Option上使用Future.sequence的方法,不幸的是你必须将它们连接在一起.
要么作为一种快速方法:
def swap[M](x: Option[Future[M]]): Future[Option[M]] =
Future.sequence(Option.option2Iterable(x)).map(_.headOption)
Run Code Online (Sandbox Code Playgroud)
注意我发现隐含Option.option2Iterable已经在我的范围内了.所以你可能不需要提供它,将代码减少到Future.sequence(x).map(_.headOption)
或者您可能更喜欢扩展方法:
implicit class OptionSwitch[A](f: Option[Future[A]]) {
import scala.concurrent.Future
def switch: Future[Option[A]] = Future.sequence(Option.option2Iterable(f))
.map(_.headOption)
}
val myOpt = Option(Future(3))
myOpt.switch
Run Code Online (Sandbox Code Playgroud)