繁体   English   中英

链接 Scala 嵌套期货

[英]Chaining Scala nested futures

我在 Scala 中链接期货时遇到了一些麻烦。 假设我有以下内容:

def fetchInts(s: String): Future[List[Int]] = Future {
  (0 to s.length).toList
}

def fetchChars(a: Int): Future[List[Char]] = Future {
  ("a" * a).toList
}

对于给定的String我想获取Int s,然后对于每个获取的Int我想获取Char s,所有这些都尽可能异步。 我想要得到的 output 类型是Future[List[(Int, List[Char])]]并且在语义上我想做这样的事情:

def fetch(s: String): Future[List[(Int, List[Char])]] = {
  for {
    as <- fetchInts(s)
    a <- as
    cs <- fetchChars(a)
  } yield (a, cs)
}

当我混合ListFuture monads 时,上述内容不会进行类型检查,所以到目前为止我想出了:

def fetch(s: String): Future[List[(Int, List[Char])]] = {
  val fas: Future[List[Int]] = fetchInts(s)
  fas.flatMap { as: List[Int] =>
    val res = as.map { a: Int =>
      val fcs: Future[List[Char]] = fetchChars(a)
      fcs.flatMap(cs => Future((a, cs)))
    }
    Future.sequence(res)
  }
}

这种类型检查但看起来很笨拙,我怀疑这是否是线程最优的,因为我没有完全掌握Futures.sequence()的语义。 还有其他更简单、更惯用的方法来执行此操作吗?

Scala 中的理解是同一实体上的地图和平面地图。 在您的 fetch 方法中,它超过了期货。 它不起作用的原因as List[Int]也是如此,而不是未来。 在这个用例中,无需理解就更容易编写它。 您可以尝试以下方法:

def fetch(s: String): Future[List[(Int, List[Char])]] = {
  fetchInts(s).flatMap { ints =>
    Future.traverse(ints)(i =>
      fetchChars(i).map { chars =>
        i -> chars
      }
    )
  }
}

的结果:

println(Await.result(fetch("abrakadabra"), 2.seconds))

是:

List((0,List()), (1,List(a)), (2,List(a, a)), (3,List(a, a, a)), (4,List(a, a, a, a)), (5,List(a, a, a, a, a)), (6,List(a, a, a, a, a, a)), (7,List(a, a, a, a, a, a, a)), (8,List(a, a, a, a, a, a, a, a)), (9,List(a, a, a, a, a, a, a, a, a)), (10,List(a, a, a, a, a, a, a, a, a, a)), (11,List(a, a, a, a, a, a, a, a, a, a, a)))

来自 Scala 文档Future.traverse

使用提供的 function A => Future[B] 将 IterableOnce[A] 异步且非阻塞地转换为 Future[IterableOnce[B]]。 这对于执行并行 map 很有用。

代码在Scastie运行。

如果您毕竟想用于理解,您可以尝试:

def fetch1(s: String): Future[List[(Int, List[Char])]] = {
  for {
    ints <- fetchInts(s)
    result <- Future.traverse(ints)(i => for {
        chars <- fetchChars(i)
      } yield i -> chars)
  } yield result
}

暂无
暂无

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

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