Play WS递归分页Get请求问题:仅返回单页结果求助
问题分析与解决方案
你遇到的问题核心是递归调用时没有合并当前页和后续页的结果——你的代码在发现有下一页时,只是单独发起了下一页的请求,却把当前页处理好的结果直接丢弃了,最终只返回了最后一页的数据。
具体问题点
看这段代码里的关键逻辑:
case Some(value) => { val page = value.split("[<>]")(1) Future { processProjectIdResponse(response) } getDnaProjectsIdsWithActivity(wsClient, startTime, endTime, page) }
这里你创建了一个处理当前页结果的Future,但完全没把它和递归调用的Future关联起来,代码直接返回了递归调用的Future,当前页的结果相当于被“丢”了,最终自然只能拿到最后一页的数据。
修正后的代码
我们需要用flatMap和map把当前页的结果和递归获取的后续页结果拼接在一起:
def getDnaProjectsIdsWithActivity( wsClient: StandaloneAhcWSClient, startTime: String, endTime: String, nextPage: String = "" ): Future[Seq[Project]] = { val request = nextPage match { case "" => wsClient.url(baseUrl + projectResource) .addQueryStringParameters( "private_token" -> token, "visibility" -> "private", "archived" -> "false", "pagination" -> "keyset", "per_page" -> "1", "order_by" -> "id", "sort" -> "asc", "simple" -> "true", "last_activity_after" -> startTime, "last_activity_before" -> endTime, "owned" -> "true" ) case page: String => wsClient.url(page) } request.get().flatMap { response => val currentProjects = processProjectIdResponse(response) response.header("Link") match { // 没有下一页,直接返回当前页处理好的结果 case None => Future.successful(currentProjects) // 有下一页,先递归拿后续所有页,再和当前页结果合并 case Some(value) => val nextPageUrl = value.split("[<>]")(1) getDnaProjectsIdsWithActivity(wsClient, startTime, endTime, nextPageUrl) .map(nextProjects => currentProjects ++ nextProjects) } } }
关键修正说明
- 结果合并逻辑:当存在下一页时,先通过递归获取后续所有页的结果,再用
map把当前页的currentProjects和后续页的nextProjects拼接成一个完整的Seq,这样每一页的数据都会被累加进来。 - 规范Future创建:用
Future.successful()替代Future { ... }来包装已经处理好的同步结果,这是Scala中处理同步转异步的更规范写法,避免不必要的线程调度开销。 - 可读性优化:把变量
page改成nextPageUrl,让代码意图更清晰,后续维护也更方便。
这样修改后,递归函数会逐层把每一页的结果累加起来,最终返回所有分页数据的完整集合。
内容的提问来源于stack exchange,提问作者Peter Katz
相关产品推荐
相关产品推荐

