我正在使用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[?]
或者,如何迭代未来的集合以及每个元素加载另一个集合的未来会有什么更好的方法?
看看这是否让你接近你所追求的。
// 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
你只能在一个理解中使用一种类型的monad,因为它只是flatMap和map的语法糖。
你应该在整个理解过程中使用相同的类型。
你不能让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)