等待Scala中具有组合选项的期货列表

等待Scala中具有组合选项的期货列表,scala,future,Scala,Future,我必须从带有Scala的RESTAPI中获取给定列表中每个文件的问题列表。我想并行处理这些请求,并使用库来实现这一点。我的方法是从Java框架中调用的,我必须在这个方法的末尾等待所有未来的结果,以便将总体结果返回到框架。这是我的密码: defetchresourceasjson(filePath:String):dispatch.Future[json4s.JValue] def extractLookupId(json:org.json4s.JValue):选项[字符串] def findLo

我必须从带有Scala的RESTAPI中获取给定列表中每个文件的问题列表。我想并行处理这些请求,并使用库来实现这一点。我的方法是从Java框架中调用的,我必须在这个方法的末尾等待所有未来的结果,以便将总体结果返回到框架。这是我的密码:

defetchresourceasjson(filePath:String):dispatch.Future[json4s.JValue]
def extractLookupId(json:org.json4s.JValue):选项[字符串]
def findLookupId(filePath:String):Future[选项[String]]=
for(json)
(f,findIssues(lookupId))//我想在这里生成一个元组(String,Seq[Issue])
}
}
Future.sequence(issuesByFile)onComplete{
case Success(x)=>finalResultPromise.Success(x)/(2)如何在此处返回x?
case Failure(x)=>/(3)如何从此处返回null?
}
//TODO将finalResultPromise转换为Java映射
}
这个代码片段有几个问题。首先,我没有得到我期望的
issuesByFile
(1)的类型。如果
findLookUpId
无法找到查找ID(即
None
),我只想忽略它的结果。我在各种教程中读过
Future[Option[X]]
在函数组合和Scala中的表达式中不容易处理。因此,我也很好奇正确处理这些问题的最佳实践是什么

第二,我不得不等待所有的未来完成,但不知道如何将结果返回给调用Java框架(2)。我可以在这里使用承诺来实现这一点吗?如果可以,我该怎么做

最后但并非最不重要的一点是,如果出现任何错误,我只想从
返回
null
,这是JavaFramework调用的,但不知道如何返回(3)

非常感谢您的帮助

谢谢, Michael有几点:

  • (1)中的第一个问题是,如果
    findLookupId
    返回
    None
    ,则您无法处理这种情况。您需要决定在这种情况下要做什么。整个过程失败?是否将该文件从列表中排除
  • (1)中的第二个问题是,
    findIssues
    本身将返回一个
    Future
    ,您需要
    map
    才能构建结果元组
  • 有一个快捷方式可用于
    map
    Future.sequence
    Future.transverse
  • 如果您无法更改方法的结果类型,因为Java接口是固定的,并且无法更改以支持未来本身,那么您必须等待未来完成。请使用
    Await.ready
    Await.result
    执行此操作
考虑到所有这些因素,选择忽略找不到id的文件会导致以下代码:

// `None` in an entry for a file means that no id could be found
def entryForFile(file: String): Future[(String, Option[Seq[Issue]])] =
  findLookupId(file).flatMap { 
    // the need for this kind of pattern match shows 
    // the difficulty of working with `Future[Option[T]]`
    case Some(id) ⇒ findIssues(id).map(issues ⇒ file -> Some(issues))
    case None     ⇒ Future.successful(file -> None)
  }

def thisIsCalledByJavaFramework(): java.util.Map[String, java.util.List[Issue]] = {
  val issuesByFile: Future[Seq[(String, Option[Seq[Issue]])]] =
    Future.traverse(getFilePathsToProcess)(entryForFile)

  import scala.collection.JavaConverters._
  try
    Await.result(issuesByFile, 10.seconds)
      .collect {
        // here we choose to ignore entries where no id could be found
        case (f, Some(issues)) ⇒ f -> issues
      }
      .toMap.mapValues(_.asJava).asJava
  catch {
    case NonFatal(_) ⇒ null
  }
}

非常容易理解的解释和工作代码。谢谢!