我必须从带有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)。
非常感谢任何帮助。
谢谢,迈克尔
几点:
考虑到所有这些因素并选择忽略找不到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