[英]Extract value from Future using Cats
我正在尝试为 GitHub 的 API 编写一个小型库。 我正在尝试模拟Github4s 库的行为,这里是这个库的一个例子:
val user1 = Github(accessToken).users.get("rafaparadela")
object ProgramEval {
val u1 = user1.exec[Eval, HttpResponse[String]]().value
}
import cats.implicits._
import github4s.GithubResponses.GHResult
ProgramEval.u1 match {
// Here the actual value of the request is returned,
// not the same as Future's onComplete, where the return type is Unit
case Right(GHResult(result, status, headers)) => result.login
case Left(e) => e.getMessage
}
我引用文档:
每个 Github4s API 调用都会返回一个 GHIO[GHResponse[A]],它是 Free[Github4s, GHResponse[A]] 的别名。
GHResponse[A] 又是 Either[GHException, GHResult[A]] 的类型别名。
GHResult 包含 Github 给出的结果 A 以及响应的状态码和标头:
在某些时候,他们正在使用HttpClient.scala发出HttpRequest
我怎么能自己复制这种行为? 我曾尝试像示例中那样使用 Cats.Eval ,但最终得到了相同的Future[String]
。
此外,我在提出请求时面临一些嵌套问题,例如,要获取组织的贡献者列表,我需要提出两个HttpRequest
:
这个结果在Future[List[Future[Users]]]
上,我面临与上面相同的问题,为了获得结果,我必须这样做:
(result:Future[List[Future[Users]]]) onComplete { users =>
users.foreach {
_ onComplete {
// Process result
}
}
}
但我想将值返回为github4s
。 我一直在阅读有关Cats 的 Applicative 和 Traversable Functors 的文章,但运气不佳。
您可以使用Future.sequence
将List[Future]
转换为Future[List]
,然后压缩嵌套的期货。
结果代码:
val input: Future[List[Future[Users]]] = ???
implicit val ec: ExecutionContext = ExecutionContext.global
val result: Future[List[Users]] = input.flatMap(list => Future.sequence(list))
不知道为什么你认为这个问题会被猫解决。 看来您最终想要的是String
(正文值),而不是Future[String]
。
从 Future 中提取值的唯一方法是使用Await
阻止主线程等待它。 由于这不是很有效,您可以像以前一样使用onComplete
创建回调。
需要注意的重要一点是,一旦你在Future
中包装了一些东西,大多数时候你不想取回它。 当您这样做时,它通常位于程序的边缘(例如您的主线程)。
让我们来解决您的问题: val f = Future[List[Future[Users]]]
。 要取消嵌套,您需要:
f.flatMap(Future.sequence)
为您提供Future[List[Users]]
。
Future.sequence
将使Future[List[Future[Users]]]
变成Future[Future[List[Users]]]
。 它将列表中的所有期货合并为一个。 任何失败的未来都会使外部未来成为失败。 如果你不想这样,你可以.recover
每个内在的 Future。
f.flatMap
将使Future[Future[List[Users]]
变成Future[List[Users]]
。 它在外部 Future 完成后运行内部 Future。 与上面的错误处理相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.