簡體   English   中英

Scala解析多個Future並獲取Map(String,AnyRef)

[英]Scala resolve multiple Futures and get a Map(String, AnyRef)

我目前正在嘗試一次解決多個期貨,但是由於其中一些可能會失敗,因此如果其中一個失敗,我不想全部失敗,而是以Map(String, AnyRef) (意味着使用將來的名稱進行映射,並將響應轉換為所需的名稱)。

目前,我有以下內容:

val fsResp = channelList.map {
  channelRef => channelRef.ask(ReportStatus).mapTo[EventMessage]
}

Future.sequence(fsResp).onComplete{
  case Success(resp: Seq[EventMessage]) =>
    resp.foreach { event => Supervisor.foreach(_ ! event) }

    val channels = loadConfiguredComponents()
      .collect {
        case ("processor" | "external", components) => components.map {
          case (name, config: Channel) =>
            (name, serializeDetails(config, resp.find(_.channel == ChannelName(name))))
        }
      }.flatten.toMap

    val event = EventMessage(...)

    Supervisor.foreach(_ ! event)

  case Failure(exception) => originalSender ! replayError(exception.getMessage)

}

但是,如果其中任何一個失敗,則此操作將失敗。 那么,如何才能得到Map(channelRef.path.name, event() | exception)

謝謝!

您可以使用fallbackTo以避免失敗。 在此示例中,我將Future [T]更改為Future [Option [T]],以回退到None,然后刪除None元素。

import scala.concurrent.ExecutionContext.Implicits.global

def method(value:Int) = { Thread.sleep(2000); println(value); value  }

println("start")

val eventualNone = Future.successful(None)

val futures = List(Future(method(1)), Future(method(2)), Future(method(3)), Future(throw new RuntimeException))

val withoutFailures = futures.map(_.map(Option.apply).fallbackTo(eventualNone))

Future.sequence(withoutFailures).map(_.flatten).onComplete {
  case Success(values) => println(values)
  case Failure(ex:Throwable) => println("FAIL")
}

Thread.sleep(5000)

產量

start
1
3
2
List(1, 2, 3)

如果您想知道失敗的原因,可以將其更改為Either [Throwable,T]而不是Option [T]。

此代碼始終為Success(關於Future結果),因此您需要檢查您的值以了解所有期貨是否失敗。

要從Future列表中捕獲成功/失敗的值,您可以首先將map/recover應用於每個值,然后使用Future.sequence將結果列表轉換為Future的List[Either[Throwable,EventMessage]] ,如圖所示在下面的簡單示例中:

import scala.concurrent.{Future, Await}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

case class EventMessage(id: Int, msg: String)

val fsResp = List(
  Future{EventMessage(1, "M1")}, Future{throw new Throwable()}, Future{EventMessage(3, "M3")}
)

val f = Future.sequence(
  fsResp.map( _.map{ resp =>
    // Do stuff with `resp`, add item to `Map()`, etc ...
    Right(resp)
  }.
  recover{ case e: Throwable =>
    // Log `exception` info, etc ...
    Left(e)
  } )
)

Await.result(f, Duration.Inf)
// f: scala.concurrent.Future[List[Product with Serializable with scala.util.
//   Either[Throwable,EventMessage]]] = Future(Success(List(
//     Right(EventMessage(1,M1)), Left(java.lang.Throwable), Right(EventMessage(3,M3))
//   )))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM