在未来序列中迭代未来序列

Iterate sequence of future in sequence of futures

我正在开发一个用 Scala 编写的 PlayFramework 应用程序。

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

图书资料库:

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[?]

或者迭代未来集合并为每个元素加载另一个未来集合的更好方法是什么?

You can only use one type of monad in a for comprehension, since it is just syntactic sugar for flatMap and map.

在这里查看完整的描述:

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

// 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

你应该在整个 for-comprehension 中使用相同的类型。

你不能在同一个 for-comprehension 中有 books:Future[Seq[Books]bookList: Seq[Book]

您还可以使用 Future.sequence

Seq[Future[Something]] 转换为 Future[Seq[Something]]

所以,这样的事情应该可行

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