【问题标题】:Recursive HTTP-requests in ScalaScala 中的递归 HTTP 请求
【发布时间】:2018-10-22 18:49:27
【问题描述】:

我需要做递归请求,然后将所有模型收集到一个列表中,但不知道该怎么做。请告诉我我的想法是否正确?

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")
      }
    }
  }

}

【问题讨论】:

  • 有趣。是否明确要求您生成递归 http 请求,例如在课堂环境中?还是您正在使用此机制解决一些业务问题?
  • 考虑这个:xyproblem.info

标签: scala jackson gitlab gitlab-api


【解决方案1】:

您在此处处理的主要问题是您试图将已有的数据 (List[MergeRequest]) 与您将来要检索的数据 (Future[List[MergeRequest]]) 结合起来。您需要做一些事情来处理这种情况:

  • 在 HTTP 请求的结果上使用 flatMap 而不是 map。这允许您在递归内部发出更多 HTTP 请求,但将它们映射回单个 Future
  • 在递归结果上调用 map fetchMergeRequests(nextPage) 以将您已有的数据与来自递归的未来数据结合起来。
  • 将另一个列表包装在 Future.successful() 中,因为 flatMap 要求所有模式匹配都返回 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")
    }
  }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2017-11-28
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多