Scala期货和承诺回调基础

Scala期货和承诺回调基础,scala,asynchronous,concurrency,promise,future,Scala,Asynchronous,Concurrency,Promise,Future,我是Scala期货的初学者/承诺 我正试图使用期货(使用回调)来实现这一点: 获取可用的Git存储库 获取每个存储库的贡献者 获取每个存储库的自述文件 最后,为每个存储库创建一个GitData响应,其中包含存储库URL、贡献者和自述文件 代码如下: // Final write container to hold the result. val promise = Promise[List[GitData]]() val repositoriesF = Future { GitDriv

我是Scala
期货的初学者
/
承诺

我正试图使用
期货
(使用回调)来实现这一点:

  • 获取可用的Git存储库
  • 获取每个存储库的贡献者
  • 获取每个存储库的自述文件
  • 最后,为每个存储库创建一个GitData响应,其中包含存储库URL、贡献者和自述文件
代码如下:

// Final write container to hold the result.
val promise = Promise[List[GitData]]()

val repositoriesF = Future {
  GitDriver.repositoriesOf(request.user)
}

val gitRepositories = Promise[List[GitRepository]]()

repositoriesF onSuccess {
  case repositories => {
    val contributors = Promise[List[Contributor]]()
    val contributorsF = Future(repositories.map(GitDriver.contributors))
    val readMe = Promise[List[String]]
    val readMeF = Future(repositories.map(GitDriver.readme))

    contributorsF.onSuccess {
      case contrib => contributors.success(contrib.flatten)
    }

    readMeF.onSuccess {
      case r => readMe.success(r)
    }

    val extractedContributors = contributors.future.value
    val extractedReadme = readMe.future.value
    println(extractedContributors.size)
    println(extractedReadme.size)
  }
}

Await.ready(repositoriesF, Duration.Inf)
贡献者和自述文件的大小始终为零

我解决这个问题的方法是,我可以通过
Futures
对贡献者和自述者的提取进行视差化,因为它们彼此不依赖。他们所需要的只是一个存储库对象


我错过了什么?我确信有更多优雅的解决方案用于理解、地图、DSL等,但我只是好奇地想弄清这一点!谢谢。

目前,您正在打印贡献者的大小,并且自述未来可能尚未完成,因此
贡献者.future.value
将不返回任何值

您可以尝试以下方法:

val repositoriesF = Future {
  GitDriver.repositoriesOf(request.user)
}

val contributorsAndReadmeFuture = for {
  repositories <- repositoriesF
  contributors <- Future(repositories.map(GitDriver.contributors))
  readme <- Future(repositories.map(GitDriver.readme))
} yield (contributors, readme)

contributorsAndReadmeFuture onSuccess {
  case (constributors, readme) => 
    println(constributors.size)
    println(readme.size)
}
val repositoriesF=未来{
GitDriver.repositoriesOf(request.user)
}
val供款人和ADMEFUTURE=for{

存储库您正在做一些奇怪的事情。根据您的问题,主要问题是您正在打印此块中的值:

repositoriesF onSuccess {
   case repositories => {
      ...
因此,从某种意义上说,您只是在等待第一次异步计算,并且只为您需要的其他信息(自述文件和贡献者)设置了回调。在设置回调之后,这些都没有完成,也没有结果

第二件奇怪的事情是,你在第一次计算中做的是
Await()
,而不是在其他计算中。很可能你想等待所有可用的信息

你做的第三件奇怪的事是使用了太多的承诺。你使用承诺不是在你想得到一些结果的时候,而是在你必须把未来还给别人,并且需要一种方式来完成未来的时候,当你不再能够接近未来本身的时候

至于如何解决您的问题,我将使用以下理解:

val futureGitData = for {
  repos <- Future { GitDriver.repositoriesOf(request.user) }
  repo <- repos
  readme <- Future { GitDriver.readme(repo) } 
  contributors <- Future { GitDriver.contributors(repo) } 
} yield (repo, readme, contributors)
val futureGitData=for{

回购您的
未来。在
未来(…)
成功时设置的
未来
承诺
之前,执行
值和
println

与以下各项相比,
未来
的值仍然是

val p = Promise[Int]()
p.future.value
// Option[scala.util.Try[Int]] = None
p.future.value.size
// Int = 0
由于您希望继续使用您的解决方案,您可以执行以下操作(无需多余的
承诺
):


虽然这种方法可能是合理的,但请记住github您可以做到(不说这是问题的原始原因)是的,我理解这一点-但我肯定在限额之内。:-)在这方面,我将如何创建我的响应(即GitData)-这是每个存储库。
案例类GitData(repoorl:String,owner:owner,readmeContents:String,contributors:List[Contributor],programmingLanguages:List[String])
这将很困难,因为您无法从回调函数返回某些内容。我建议您仔细看看Daniel L的答案。
repositoriesF onSuccess {
  case repositories =>
    val contributorsF = Future(repositories.flatMap(GitDriver.contributors))
    val readMeF = Future(repositories.map(GitDriver.readme))

    contributorsF zip readMeF onSuccess {
      case (contrib, readme) => 
        println(contrib.size)
        println(readme.size)
    }
}