簡體   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