Scala期货和承诺回调基础
我是ScalaScala期货和承诺回调基础,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
期货的初学者
/承诺
我正试图使用期货(使用回调)来实现这一点:
- 获取可用的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)
}
}