使用 Cats 从 Future 中提取价值
Extract value from Future using Cats
我正在尝试为 GitHub 的 API 编写一个小型库。我正在尝试模拟 Github4s's library 的行为,这里是这个库的一个例子:
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
}
我正在引用文档:
Every Github4s API call returns a GHIO[GHResponse[A]] which is an alias for Free[Github4s, GHResponse[A]].
GHResponse[A] is, in turn, a type alias for Either[GHException, GHResult[A]].
GHResult contains the result A given by Github as well as the status code and headers of the response:
在某些时候,他们正在 HttpRequest
使用 HttpClient.scala
我怎样才能自己复制这种行为?我试过在示例中使用 Cats.Eval,但我最终得到了相同的 Future[String]
.
此外,我在提出请求时遇到了一些嵌套问题,例如,要获取组织的贡献者列表,我需要制作两个 HttpRequest
:
- 一个用于获取组织 repos
- 每个 repo 一个,以获得贡献者列表
这个结果就Future[List[Future[Users]]]
,和我遇到和上面一样的问题,为了得到结果,我必须做:
(result:Future[List[Future[Users]]]) onComplete { users =>
users.foreach {
_ onComplete {
// Process result
}
}
}
不过我想把return的值设为github4s
。我一直在阅读有关 Cats's Applicative and 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
(body value),而不是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]]]
。它将列表中的所有 Futures 合并为一个。任何失败的未来都会使外在的未来失败。如果你不想这样,你可以 .recover
每个内部 Future。
f.flatMap
会使Future[Future[List[Users]]
变成Future[List[Users]]
。它在外部 Future 完成后运行内部 Future。此处的错误处理与上面相同。
我正在尝试为 GitHub 的 API 编写一个小型库。我正在尝试模拟 Github4s's library 的行为,这里是这个库的一个例子:
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
}
我正在引用文档:
Every Github4s API call returns a GHIO[GHResponse[A]] which is an alias for Free[Github4s, GHResponse[A]].
GHResponse[A] is, in turn, a type alias for Either[GHException, GHResult[A]].
GHResult contains the result A given by Github as well as the status code and headers of the response:
在某些时候,他们正在 HttpRequest
使用 HttpClient.scala
我怎样才能自己复制这种行为?我试过在示例中使用 Cats.Eval,但我最终得到了相同的 Future[String]
.
此外,我在提出请求时遇到了一些嵌套问题,例如,要获取组织的贡献者列表,我需要制作两个 HttpRequest
:
- 一个用于获取组织 repos
- 每个 repo 一个,以获得贡献者列表
这个结果就Future[List[Future[Users]]]
,和我遇到和上面一样的问题,为了得到结果,我必须做:
(result:Future[List[Future[Users]]]) onComplete { users =>
users.foreach {
_ onComplete {
// Process result
}
}
}
不过我想把return的值设为github4s
。我一直在阅读有关 Cats's Applicative and 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
(body value),而不是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]]]
。它将列表中的所有 Futures 合并为一个。任何失败的未来都会使外在的未来失败。如果你不想这样,你可以 .recover
每个内部 Future。
f.flatMap
会使Future[Future[List[Users]]
变成Future[List[Users]]
。它在外部 Future 完成后运行内部 Future。此处的错误处理与上面相同。