Scala 中的递归 HTTP 请求
Recursive HTTP-requests in Scala
我需要递归请求,然后将所有模型收集到一个列表中,但不明白该怎么做。请告诉我我的想法是否正确?
package kindSir.main
import dispatch.Defaults._
import dispatch._
import kindSir.models._
import org.json4s._
import org.json4s.jackson.JsonMethods._
object ApplicationMain extends App {
def fetchMergeRequests(startPage: Int = 1): Future[List[MergeRequest]] = {
val requestsUrl = url(s"https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/merge_requests?state=opened&per_page=3&page=${startPage}")
Http(requestsUrl).map { res =>
(parse(res.getResponseBody), res.getHeader("X-Next-Page").toInt) match {
case (list@JArray(_), nextPage: Int) =>
val currentList: List[MergeRequest] = MergeRequest.parseList(list).get
val nextPageListFuture: Future[List[MergeRequest]] = fetchMergeRequests(nextPage)
// And how to merge these two lists?
case (list@JArray(_), _) => MergeRequest.parseList(list).get
case _ => throw new RuntimeException(s"No merge requests for project found")
}
}
}
}
您在这里要处理的主要问题是您试图将已有的数据 (List[MergeRequest]
) 与您将来检索的数据 (Future[List[MergeRequest]]
) 结合起来。要处理这种情况,您需要做几件事:
- 对 HTTP 请求的结果使用
flatMap
而不是 map
。这允许您在递归内部发出更多 HTTP 请求,但将它们映射回单个 Future
.
- 对递归的结果调用
map
fetchMergeRequests(nextPage)
以将您已有的数据与递归的未来数据相结合。
- 将另一个列表包装在
Future.successful()
中,因为 flatMap
要求所有模式匹配 return a Future
— 除了例外。
我不熟悉你使用的库,所以我没有测试过,但我认为你的代码应该像这样工作:
def fetchMergeRequests(startPage: Int = 1): Future[List[MergeRequest]] = {
val requestsUrl = url(s"https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/merge_requests?state=opened&per_page=3&page=${startPage}")
Http(requestsUrl).flatMap { res =>
(parse(res.getResponseBody), res.getHeader("X-Next-Page").toInt) match {
case (list@JArray(_), nextPage: Int) =>
val currentList: List[MergeRequest] = MergeRequest.parseList(list).get
val nextPageListFuture: Future[List[MergeRequest]] = fetchMergeRequests(nextPage)
nextPageListFuture.map(nextPageList => currentList ++ nextPageList)
case (list@JArray(_), _) =>
Future.successful(MergeRequest.parseList(list).get)
case _ => throw new RuntimeException(s"No merge requests for project found")
}
}
}
我需要递归请求,然后将所有模型收集到一个列表中,但不明白该怎么做。请告诉我我的想法是否正确?
package kindSir.main
import dispatch.Defaults._
import dispatch._
import kindSir.models._
import org.json4s._
import org.json4s.jackson.JsonMethods._
object ApplicationMain extends App {
def fetchMergeRequests(startPage: Int = 1): Future[List[MergeRequest]] = {
val requestsUrl = url(s"https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/merge_requests?state=opened&per_page=3&page=${startPage}")
Http(requestsUrl).map { res =>
(parse(res.getResponseBody), res.getHeader("X-Next-Page").toInt) match {
case (list@JArray(_), nextPage: Int) =>
val currentList: List[MergeRequest] = MergeRequest.parseList(list).get
val nextPageListFuture: Future[List[MergeRequest]] = fetchMergeRequests(nextPage)
// And how to merge these two lists?
case (list@JArray(_), _) => MergeRequest.parseList(list).get
case _ => throw new RuntimeException(s"No merge requests for project found")
}
}
}
}
您在这里要处理的主要问题是您试图将已有的数据 (List[MergeRequest]
) 与您将来检索的数据 (Future[List[MergeRequest]]
) 结合起来。要处理这种情况,您需要做几件事:
- 对 HTTP 请求的结果使用
flatMap
而不是map
。这允许您在递归内部发出更多 HTTP 请求,但将它们映射回单个Future
. - 对递归的结果调用
map
fetchMergeRequests(nextPage)
以将您已有的数据与递归的未来数据相结合。 - 将另一个列表包装在
Future.successful()
中,因为flatMap
要求所有模式匹配 return aFuture
— 除了例外。
我不熟悉你使用的库,所以我没有测试过,但我认为你的代码应该像这样工作:
def fetchMergeRequests(startPage: Int = 1): Future[List[MergeRequest]] = {
val requestsUrl = url(s"https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/merge_requests?state=opened&per_page=3&page=${startPage}")
Http(requestsUrl).flatMap { res =>
(parse(res.getResponseBody), res.getHeader("X-Next-Page").toInt) match {
case (list@JArray(_), nextPage: Int) =>
val currentList: List[MergeRequest] = MergeRequest.parseList(list).get
val nextPageListFuture: Future[List[MergeRequest]] = fetchMergeRequests(nextPage)
nextPageListFuture.map(nextPageList => currentList ++ nextPageList)
case (list@JArray(_), _) =>
Future.successful(MergeRequest.parseList(list).get)
case _ => throw new RuntimeException(s"No merge requests for project found")
}
}
}