当前位置: 首页 > 知识库问答 >
问题:

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

雷硕
2023-03-14

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

def fetchResourceAsJson(filePath: String): dispatch.Future[json4s.JValue]

def extractLookupId(json: org.json4s.JValue): Option[String]

def findLookupId(filePath: String): Future[Option[String]] =
  for (json <- fetchResourceAsJson(filePath))
    yield extractLookupId(json)

def searchIssuesJson(lookupId: String): Future[json4s.JValue]

def extractIssues(json: org.json4s.JValue): Seq[Issue]

def findIssues(lookupId: String): Future[Seq[Issue]] =
  for (json <- searchIssuesJson(componentId))
    yield extractIssues(json)

def getFilePathsToProcess: List[String]


def thisIsCalledByJavaFramework(): java.util.Map[String, java.util.List[Issue]] = {
  val finalResultPromise = Promise[Map[String, Seq[Issue]]]()

  // (1) inferred type of issuesByFile not as expected, cannot get 
  // the type system happy, would like to have Seq[Future[(String, Seq[Issue])]]

  val issuesByFile = getFilePathsToProcess map { f => 
    findLookupId(f).flatMap { lookupId =>
     (f, findIssues(lookupId)) // I want to yield a tuple (String, Seq[Issue]) here
    }
  }
  Future.sequence(issuesByFile) onComplete {
    case Success(x) => finalResultPromise.success(x) // (2) how to return x here?
    case Failure(x) => // (3) how to return null from here?
  }

  //TODO transform finalResultPromise to Java Map
}

这段代码有几个问题。首先,我没有得到我期望的< code>issuesByFile (1)的类型。如果< code>findLookUpId无法找到查找Id(即< code>None),我只想忽略它的结果。我在各种教程中读到过< code>Future[Option[X]]在Scala中的函数组合和for表达式中不容易处理。所以我也很好奇正确处理这些问题的最佳实践是什么。

其次,我必须以某种方式等待所有期货完成,但不知道如何将结果返回到调用Java框架(2)。我能在这里使用promise来实现这一点吗?如果是,我该怎么做?

最后但同样重要的是,如果有任何错误,我只想从< code > thisiskalledbyjavaframework 返回< code>null,但不知道如何返回(3)。

非常感谢任何帮助。

谢谢,迈克尔

共有1个答案

邓越泽
2023-03-14

几点:

    < Li >(1)的第一个问题是,您没有处理< code>findLookupId返回< code>None的情况。在这种情况下,你需要决定怎么做。整个过程失败?从列表中排除该文件? < Li >(1)的第二个问题是< code>findIssues本身将返回一个< code>Future,您需要< code >映射它,然后才能构建结果元组 < li >有一个快捷方式可用于< code>map和< code > future . sequence :< code > future . traverse < li >如果因为Java接口是固定的且不能更改以支持期货本身而不能更改方法的结果类型,则必须等待期货完成。使用< code>Await.ready或< code>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
  }
}
 类似资料:
  • 我启动了几个异步进程,如果需要,这些进程反过来可以启动更多的进程(想想遍历目录结构或类似的东西)。每个进程都会返回一些东西,最后我想等待所有这些进程的完成,并安排一个函数来处理结果集合。 我的解决方案尝试使用可变的(我不断添加我生成的期货)和来安排一些函数在此缓冲区中列出的所有这些期货完成后运行。 我准备了一个简单的例子来说明这个问题: 它首先调度和期货,然后将在1秒后的分辨率中调度。本身将在2秒

  • 我正在使用: Scala 2.10 游戏2.1 目前,我正在使用 类,但我愿意尝试另一个 API。 我很难将多个期货的结果组合成一个列表[(String, String)]。 以下 方法成功地将单个 Future 的结果返回到 HTML 模板: 方法执行 Web 服务 API 调用并返回 Future[play.api.libs.ws.Response]。方法 向 HTML 模板返回 List[(

  • 在用收益结构组合期货时,有些有副作用,有些没有,我引入了竞争条件,因为取决于副作用的未来并没有将副作用的结果作为论据。 简而言之: 未来b读取由来自未来a的副作用改变的值,但是未来a不明确依赖于未来b的结果,因此可能在b完成读取之前发生。 为了解决这个问题,我的同事引入了一个虚拟函数,将b的结果作为参数并简单地将其丢弃。这样做是为了使依赖显式化。 实际代码如下: 在这种情况下,未来 b 为 带哑参

  • 我有两个在未来发生的计算,如下所示: 我希望它能够运行,以便comp2总是在comp1完成后运行!我知道使用一个表达,我可以组成这两个Future的喜欢。 什么能保证comp1在comp2之前完成?我的意思是这些是发生在不同线程中的计算,并且不能保证运行的顺序。有没有一种方法可以保证没有阻塞的顺序?

  • 假设我有几个未来,需要等到它们中的任何一个失败或全部成功。 例如:设有3个期货:、、。 > 如果成功而失败,我不会等待(并将失败返回给客户端)。 如果<code>f2</code>失败,而<code>f1</code>和<code>f3</code>仍在运行,我不会等待它们(并返回故障) 如果成功,然后成功,我继续等待。 你将如何实现它?

  • 我希望像下面这样的代码可以等待这两种未来,但是没有。 我以为< code>seq.onComplete会在完成自身之前等待它们全部完成,但事实并非如此;它会导致: 在scala.concurrent.Future的源代码中有点难以遵循,我想知道如何实现等待(动态大小的)序列的所有原始未来的并行,或者这里可能有什么问题。 编辑:相关问题:https://worldbuilding.stackexch