按期货顺序迭代未来序列

问题描述 投票:1回答:3

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

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

图书存放处:

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

或者,如何迭代未来的集合以及每个元素加载另一个集合的未来会有什么更好的方法?

scala future flatmap
3个回答
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

0
投票

你只能在一个理解中使用一种类型的monad,因为它只是flatMap和map的语法糖。

在这里看到整个描述:https://stackoverflow.com/a/33402543/2750966


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)
© www.soinside.com 2019 - 2024. All rights reserved.