简体   繁体   English

遍历列表时处理 Future[Option[T]]

[英]Handle Future[Option[T]] when traversing a List

  def getCommentIds(
      commentTargetId: Long,
      sortOrder: CommentOrderEnum): Future[Seq[CommentStatsBO]]

def getCommentDetail(commentId: Long): Future[Option[CommentDetailDTO]]

def getCommentListWithDetail(
      targetId: Long,
      sortOrder: CommentOrderEnum,
      page: Int): Future[Seq[CommentDetailDTO]] = {
    commentModel.getCommentIds(targetId, sortOrder).flatMap {
      commentStatsBOSeq =>
        Future.traverse(commentStatsBOSeq) { commentStatsBO =>
// commentDetail is a Future[Option[T]]
          val commentDetail = getCommentDetail(commentStatsBO.iId)
          commentDetail.map(commentOpt =>
            commentOpt
// merge the stat info into the comment detail
              .map(_.copy(replyCount = Some(commentStatsBO.replyCount)))
              .getOrElse(CommentDetailDTO))

        }

    }
  }

case class CommentDetailDTO(
    id: Long,
    author: JsObject,
    detail: CommentDetail,
replyCount: Option[Int] = None
)

Firstly, the function getCommentIds returns a sequence of CommentStatsBO, then traversing it and try to get detail for every comment.首先,函数getCommentIds返回一个 CommentStatsBO 序列,然后遍历它并尝试获取每个评论的详细信息。 Here comes the question, getCommentDetail returns a Future which contains an option since the comment maybe not found, in this case, how to filter those ones whose option is None?问题来了, getCommentDetail返回一个包含选项的 Future,因为可能找不到注释,在这种情况下,如何过滤那些选项为 None 的选项? I have tried getOrElse , but don't know how to define an empty object just like Json.obj() since case class doesn't support.我试过getOrElse ,但不知道如何像Json.obj()一样定义一个空对象,因为case class不支持。 Thanks!谢谢!

Don't try to do too many things at the same time, rather build the solution you need step by step.不要试图同时做太多事情,而是逐步构建您需要的解决方案。

If you do a simple Future.traverse using just getCommentDetail you will get a Future[Seq[Option[CommentDetailDTO]]] which then you can map and use collect with the Seq to remove the Option如果你Future.traverse使用getCommentDetail做一个简单的Future.traverse你会得到一个Future[Seq[Option[CommentDetailDTO]]]然后你可以map和使用collectSeq来删除Option

def getCommentListWithDetail(
  targetId: Long,
  sortOrder: CommentOrderEnum,
  page: Int
): Future[Seq[CommentDetailDTO]] =
  commentModel.getCommentIds(targetId, sortOrder).flatMap { commentStatsBOSeq =>
    Future.traverse(commentStatsBOSeq) { commentStatsBO =>
      getCommentDetail(commentStatsBO.iId)
    } map { commentOptionalDetails =>
      commentOptionalDetails.collect {
        case Some(commentDetail) => commentDetail
      }
    }
  }

Or if you use cats , you can use traverseFilter或者,如果您使用,则可以使用traverseFilter

import cats.syntax.all._

def getCommentListWithDetail(
  targetId: Long,
  sortOrder: CommentOrderEnum,
  page: Int
): Future[Seq[CommentDetailDTO]] =
  commentModel.getCommentIds(targetId, sortOrder).flatMap { commentStatsBOSeq =>
    commentStatsBOSeq.traverseFilter(getCommentDetail)
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM