Scala中如何基于Future实现未知次数的分页查询全量子评论
实现方案
这类动态次数、下一次请求依赖上一次返回结果的异步迭代场景,通过Future + 递归的方式即可实现,逻辑和你提供的同步迭代示例完全对齐:
基础实现
import scala.concurrent.{Future, ExecutionContext} def getAllChildComments(parentId: Int, pageSize: Int)(implicit ec: ExecutionContext): Future[Seq[CommentsRow]] = { // 递归辅助函数:入参为当前查询偏移量、已累计的评论列表 def recurse(offset: Int, accumulated: Seq[CommentsRow]): Future[Seq[CommentsRow]] = { getChildCommentsByParentId(parentId, offset, pageSize).flatMap { currentPage => if (currentPage.size < pageSize) { // 当前页数据量不足页长,说明无更多数据,返回累计结果+当前页 Future.successful(accumulated ++ currentPage) } else { // 还有下一页,偏移量增加页长后继续递归 recurse(offset + pageSize, accumulated ++ currentPage) } } } // 初始调用:偏移量从0开始,累计列表为空 recurse(0, Nil) }
说明
- 不需要担心栈溢出问题:每次递归调用都是在
Future的异步回调中触发,不会占用同步调用栈,和普通同步递归的栈风险有本质区别。 - 直接调用即可拿到全量子评论:例如需要页长为20时,调用
getAllChildComments(目标父评论ID, 20),返回的Future中就包含所有符合条件的子评论。
优化版本(大数据量场景)
如果子评论量非常大,每次拼接Seq会产生额外开销,可以用可变集合ListBuffer做累计优化:
import scala.collection.mutable.ListBuffer import scala.concurrent.{Future, ExecutionContext} def getAllChildComments(parentId: Int, pageSize: Int)(implicit ec: ExecutionContext): Future[Seq[CommentsRow]] = { def recurse(offset: Int, accum: ListBuffer[CommentsRow]): Future[Seq[CommentsRow]] = { getChildCommentsByParentId(parentId, offset, pageSize).flatMap { currentPage => accum.appendAll(currentPage) if (currentPage.size < pageSize) { Future.successful(accum.toSeq) } else { recurse(offset + pageSize, accum) } } } recurse(0, ListBuffer.empty[CommentsRow]) }
内容的提问来源于stack exchange,提问作者BugSource
相关产品推荐
相关产品推荐

