我有一个方法可以进行API调用并返回Future[Seq[Post]]
,每个帖子都有一个序列id
。 API调用每次调用返回200个帖子。为了获得完整的帖子序列,我在后续调用中提交最小的id
(作为maxId
)。每个Post
对象还包含一个User
对象,其中包含一个字段,指定用户发布的帖子总数。什么是以非阻塞方式完成所有用户帖子的最佳方式?
到目前为止,我有以下阻止代码:
def completeTimeline(userId: Long) = {
def getTimeline(maxId = Option[Long] = None): Seq[Post] = {
val timeline: Future[Seq[Post]] = userPosts(userId) // calls method that returns Future[Seq[Post]]
Await.result(timeline, 5.seconds)
}
def recurseTimeline(timeline: Seq[Post]): Seq[Post] = {
if (timeline.length < timeline.head.user.map(user => user.post_count).getOrElse(0)) {
val maxId = timeline.min(Ordering.by((p: Post) => p.id)).id - 1 // API call with maxId is inclusive, subtract 1 to avoid duplicates
val nextTimeline = getTimeline(maxId = Some(maxId))
val newTimeline = timeline ++ nextTimeline
recurseTimeline(newTimeline)
} else timeline
}
recurseTimeline(getTimeline())
}
答案 0 :(得分:4)
这样的事情:
def completeTimeline(userId: Long): Future[Seq[Post]] = {
def getTimeline(maxId: Option[Long] = None): Future[Seq[Post]] = {
val timeline: Future[Seq[Post]] = userPosts(userId) // calls method that returns Future[Seq[Post]]
timeline
}
def recurseTimeline(timeline: Seq[Post]): Future[Seq[Post]] = {
if (timeline.length < timeline.head.user.map(user => user.post_count).getOrElse(0)) {
val maxId = timeline.min(Ordering.by((p: Post) => p.id)).id - 1 // API call with maxId is inclusive, subtract 1 to avoid duplicates
for {
nextTimeline <- getTimeline(maxId = Some(maxId))
full <- recurseTimeline(timeline ++ nextTimeline)
} yield full
} else Future.successful(timeline)
}
getTimeline() flatMap recurseTimeline
}
基本上,你是调度每个未来完成后发生的事情(map,flatMap和for-comprehension),而不是等待它们完成。
如果我对你想要做的事情有所了解,那么代码可能会被简化。
答案 1 :(得分:1)
当您说non-blocking
与I need to check all of the Posts
不兼容时:您需要等待所有期货完成 - 从而能够在继续之前找到最低id
。正确?或者您想进一步解释您的意图吗?
继续这个假设 - 您可以将每个Future添加到列表中,然后在列表上进行迭代并在每个列表上调用Await。这实际上是获得一套期货的标准阻止机制。
如果有进一步的考虑和/或假设,那么请提供它们 - 允许为您的详细信息调整这种一般方法。