在期货序列中迭代期货序列

时间:2018-09-18 08:45:44

标签: scala future flatmap

我正在使用Scala编写的PlayFramework应用程序。

问题是在rest控制器中,我需要一个元素列表(书)以及每个子元素列表的子元素(章节)。

图书库:

def findAll(): Future[Seq[Book]] 

章节存储库:

def findByBookId(bookId: UUID): Future[Seq[Chapter]]

我想做

val books = bookRepository.findAll
val result = for {
  bookList <- books
  book <- bookList
  chapters <- chapterRepository.findByBookdId(book.id)
} yield (book, chapters)

我想拥有一本书及其各章的元组,以便以后可以将其映射到json。我做错了,因为出现错误:

[error]  required: scala.collection.GenTraversableOnce[?]

或者,一种更好的方法是如何遍历集合的未来并为每个元素加载另一个集合的未来?

3 个答案:

答案 0 :(得分:2)

看看这是否使您接近所追求的目标。

// found books (future)
val fBooks :Future[Seq[Book]] = bookRepository.findAll()

// chapters in fBooks order (future)
val fChptrs :Future[Seq[Seq[Chapter]]] = fBooks.flatMap {books =>
  Future.sequence(books.map(book =>findByBookId(book.id)))
}

// combine book with its chapters
val result :Future[Seq[(Book, Seq[Chapter])]] = for {
  books <- fBooks
  chptrs <- fChptrs
} yield books zip chptrs

答案 1 :(得分:0)

  

您只能在a中使用一种monad进行理解,因为它只是flatMap和map的语法糖。

请参阅此处的整个说明:https://stackoverflow.com/a/33402543/2750966

答案 2 :(得分:0)

您应该在理解过程中使用相同的类型。

您不能同时理解books:Future[Seq[Books]bookList: Seq[Book]

您还可以使用Seq[Future[Something]]Future[Seq[Something]]转换为Future.sequence

所以,这样的事情应该起作用

val res: Future[(Seq[Book], Seq[Chapter])] =
for {
  bookList <- books
  chapters <- Future.sequence(bookList.map(book => findByBookId(book.id)))
} yield (bookList, chapters.flatten)