Reputation: 11734
I am having trouble calling out to another function which returns a Future from within a Future.traverse. The scenario is that I have a Seq[Document] from which I need to turn them into a Future[Seq[NewsArticle]]. However, in order to do this I need to take the doc.categoryID and use it to call out to another API to build the NewsCategory, which will be returned as a Future[NewsCategory]. My problem is not knowing how to squish this in to the Future.traverse after it has returned.
Here is my scala code so far:
object NewsArticle {
def buildNewsArticles(docs:Seq[Document]):Future[Seq[NewsArticle]] = {
Future.traverse(docs) { doc =>
val categoryID = doc.catID
val title = doc.title
val pdf = doc.pdfLink
val image = doc.imageUrl
val body = doc.body
//need to call NewsCategory.buildNewsCategory(categoryID)
//but it returns a Future[NewsCategory]
//can't use for-yield because it still only yields
//a Future
future(NewsArticle( ??? ,title, pdf, image, body)
}
}
}
object NewsCategory {
def buildNewsCategory(catID:String):Future[NewsCategory] = {
// Calls external api across the wire and
// Returns a Future[NewsCategory]
}
}
// CASE CLASSES
case class NewsArticle(
category:NewsCategory,
title:String,
pdf:String,
image:String,
body:String)
case class NewsCategory(
id:String,
name:String
description:String)
Thanks for helping
Upvotes: 1
Views: 118
Reputation: 362
Maybe try this:
object NewsArticle {
def buildNewsArticles(docs:Seq[Document]):Future[Seq[NewsArticle]] = {
Future.traverse(docs) { doc =>
val categoryID = doc.catID
val title = doc.title
val pdf = doc.pdfLink
val image = doc.imageUrl
val body = doc.body
for {
cat <- NewsCategory.buildNewsCategory(categoryID)
} yield new NewsArticle(cat, title, pdf, image, body)
}
}
}
Upvotes: 1
Reputation: 8932
It sounds like you want to create a NewsArticle
instance based on the NewsCategory
returned in the future from buildNewsCategory
, which means that you were on the right track. I think the following will do what you want:
Future.traverse(docs) { doc =>
val categoryID = doc.catID
val title = doc.title
val pdf = doc.pdfLink
val image = doc.imageUrl
val body = doc.body
// This could be a for-yield instead as you note.
NewsCategory.buildNewsCategory(categoryID).map { category =>
NewsArticle(category, title, pdf, image, body)
}
}
Upvotes: 3