从Future.traverse中开始另一个Future调用

时间:2014-03-22 11:46:36

标签: scala

我在调用另一个从Future.traverse中返回Future的函数时遇到了麻烦。场景是我有一个Seq [Document],我需要将它们变成Future [Seq [NewsArticle]]。但是,为了做到这一点,我需要使用doc.categoryID并使用它来调用另一个API来构建NewsCategory,它将作为Future [NewsCategory]返回。我的问题是不知道如何在返回之后将其压入Future.traverse

到目前为止,这是我的scala代码:

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)

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

听起来您希望根据NewsArticle中未来返回的NewsCategory创建buildNewsCategory实例,这意味着您处于正确的轨道上。我认为以下内容可以满足您的需求:

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)
    }
 }

答案 1 :(得分:1)

也许试试这个:

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)

     }
  }
}