Scala 如何利用Akka一秒钟的延迟限制期货

Scala 如何利用Akka一秒钟的延迟限制期货,scala,akka,akka-stream,akka-http,Scala,Akka,Akka Stream,Akka Http,我有一个URI列表,我想请求其中的每一个URI,中间有一秒的延迟。我该怎么做 val uris: List[String] = List() // How to make these URIs resolve 1 second apart? val responses: List[Future[Response]] = uris.map(httpRequest(_)) 类似于以下内容: @tailrec def withDelay( uris: Seq[String],

我有一个URI列表,我想请求其中的每一个URI,中间有一秒的延迟。我该怎么做

val uris: List[String] = List()
// How to make these URIs resolve 1 second apart?
val responses: List[Future[Response]] = uris.map(httpRequest(_))

类似于以下内容:

  @tailrec
  def withDelay(
    uris: Seq[String], 
    delay: Duration = 1 second, 
    result: List[Future[Response]] = Nil,
  ): Seq[Future[Response]] = uris match {
     case Seq() => result.reversed
     case (head, tail@_*) => 
        val v = result.headOption.getOrElse(Future.successful(null))
          .flatMap { _ => 
            akka.pattern.after(delay, context.system.scheduler)(httpRequest(head))
          }
        withDelay(tail, delay, v :: result)
   }
这在第一次执行之前也有延迟,但我希望,如果必要的话,如何摆脱它已经足够清楚了。。。 另一个警告是,这假设所有期货都成功。一旦出现故障,所有后续处理都将中止。 如果需要不同的行为,可以将
.flatMap
替换为
.transform
或添加
.recover

如果愿意,您也可以使用
.foldLeft
编写相同的代码:

  uris.foldLeft(List.empty[Future[Response]]) { case (results, next) => 
    results.headOption.getOrElse(Future.successful(null))
      .flatMap { _ => 
        akka.pattern.after(delay, context.system.scheduler)(httpRequest(next))
      } :: results
  }.reversed

akka streams拥有它(考虑到您正在使用akka http并为akka streams添加标记)

您可以从URI列表中创建一个akka streams
,然后将每个URI转换为未来的[Response]:

def httpRequest(uri: String): Future[Response] = ???

val uris: List[String] = ???

val responses: Future[Seq[Response]] =
  Source(uris)
    .throttle(1, 1 second)
    .mapAsync(parallelism = 1)(httpRequest)
    .runWith(Sink.seq[Response])

这看起来像Java代码,而不是Scala。。。您在Scala中使用
val
var
声明变量。这不是将每个未来延迟1秒而不是一个接一个吗?就像第一个延迟1秒,第二个延迟2秒,第三个延迟3秒一样,在执行每个未来之前,添加1秒延迟。因此,有效地说,是的,第N次执行总共延迟了N秒。这不是你想要的吗?