[SCALA] 스칼라 : 목록 [미래] 미래 [목록]에 실패 미래를 무시
SCALA스칼라 : 목록 [미래] 미래 [목록]에 실패 미래를 무시
나는 목록의 미래에 선물의 임의의 길이리스트를 변환하는 방법을 찾고 있어요. 나는 Playframework, 그래서 궁극적으로 내가 정말 원하는 것은 미래 [결과]는 사용하고 있지만, 상황이 간단하게 그냥 말할 수 있도록 미래 [목록 [지능] (Future.sequence를 사용하는 것이 작업을 수행하는 일반적인 방법 ...)하지만 트위스트가있다 ... 나는 보통 주어진있어 목록은에서 약 10 ~ 20 선물을 가지고 있으며, 그 선물 중 하나가 (가) 외부 웹 서비스 요청을하고 있습니다 실패하는 것은 드문 일이 아니에요. 대신 그들 중 하나가 실패하는 경우에 그들 모두를 시도하는 데, 나는 성공한 사람들을 돌아 것들에 얻을 수 있도록하고 싶습니다.
예를 들어, 다음을 수행하는 것은 작동하지 않습니다
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Success
import scala.util.Failure
val listOfFutures = Future.successful(1) :: Future.failed(new Exception("Failure")) ::
Future.successful(3) :: Nil
val futureOfList = Future.sequence(listOfFutures)
futureOfList onComplete {
case Success(x) => println("Success!!! " + x)
case Failure(ex) => println("Failed !!! " + ex)
}
scala> Failed !!! java.lang.Exception: Failure
대신에만 예외를 받고, 나는 거기의 1과 3 점을 당길 수 있도록하고 싶습니다. 나는 Future.fold를 사용하여 시도,하지만 분명히 바로 뒤에서 Future.sequence를 호출합니다.
도움에 미리 감사드립니다!
해결법
-
==============================
1.트릭은 미래의 어느 것도 실패하지 않았다 있는지 먼저 확인하는 것입니다. .recover 당신이 미래에 모든 미래 [T] 결과를 변환하기 위해지도를 결합 할 수 있습니다, 여기 당신의 친구입니다 확신 모두] 인스턴스, 성공적인 선물로 [[T]를보십시오]가.
트릭은 미래의 어느 것도 실패하지 않았다 있는지 먼저 확인하는 것입니다. .recover 당신이 미래에 모든 미래 [T] 결과를 변환하기 위해지도를 결합 할 수 있습니다, 여기 당신의 친구입니다 확신 모두] 인스턴스, 성공적인 선물로 [[T]를보십시오]가.
참고 : 당신은 잘 여기로 옵션 또는 중 하나를 사용할 수 있지만, 특별히 트랩 예외하려면 봅니다 가장 깨끗한 방법입니다
def futureToFutureTry[T](f: Future[T]): Future[Try[T]] = f.map(Success(_)).recover(x => Failure(x)) val listOfFutures = ... val listOfFutureTrys = listOfFutures.map(futureToFutureTry(_))
그런 당신에게 [목록 [시도 [T]]]을 미래를 제공하기 위해, 이전과 Future.sequence를 사용
val futureListOfTrys = Future.sequence(listOfFutureTrys)
그런 다음 필터 :
val futureListOfSuccesses = futureListOfTrys.map(_.filter(_.isSuccess))
당신이 그들을 필요로하는 경우 당신은, 특정 장애를 당길 수 :
val futureListOfFailures = futureListOfTrys.map(_.filter(_.isFailure))
-
==============================
2.내가 케빈의 대답을했는데, 내가 스칼라 (2.11.5)의 내 버전에 글리치에 달렸다 ... 나는 그것을 수정하고, 사람이 관심이 있다면 몇 가지 추가 테스트를 썼다 ... 여기> 내 버전
내가 케빈의 대답을했는데, 내가 스칼라 (2.11.5)의 내 버전에 글리치에 달렸다 ... 나는 그것을 수정하고, 사람이 관심이 있다면 몇 가지 추가 테스트를 썼다 ... 여기> 내 버전
implicit class FutureCompanionOps(val f: Future.type) extends AnyVal { /** Given a list of futures `fs`, returns the future holding the list of Try's of the futures from `fs`. * The returned future is completed only once all of the futures in `fs` have been completed. */ def allAsTrys[T](fItems: /* future items */ List[Future[T]]): Future[List[Try[T]]] = { val listOfFutureTrys: List[Future[Try[T]]] = fItems.map(futureToFutureTry) Future.sequence(listOfFutureTrys) } def futureToFutureTry[T](f: Future[T]): Future[Try[T]] = { f.map(Success(_)) .recover({case x => Failure(x)}) } def allFailedAsTrys[T](fItems: /* future items */ List[Future[T]]): Future[List[Try[T]]] = { allAsTrys(fItems).map(_.filter(_.isFailure)) } def allSucceededAsTrys[T](fItems: /* future items */ List[Future[T]]): Future[List[Try[T]]] = { allAsTrys(fItems).map(_.filter(_.isSuccess)) } } // Tests... // allAsTrys tests // test("futureToFutureTry returns Success if no exception") { val future = Future.futureToFutureTry(Future{"mouse"}) Thread.sleep(0, 100) val futureValue = future.value assert(futureValue == Some(Success(Success("mouse")))) } test("futureToFutureTry returns Failure if exception thrown") { val future = Future.futureToFutureTry(Future{throw new IllegalStateException("bad news")}) Thread.sleep(5) // need to sleep a LOT longer to get Exception from failure case... interesting..... val futureValue = future.value assertResult(true) { futureValue match { case Some(Success(Failure(error: IllegalStateException))) => true } } } test("Future.allAsTrys returns Nil given Nil list as input") { val future = Future.allAsTrys(Nil) assert ( Await.result(future, 100 nanosecond).isEmpty ) } test("Future.allAsTrys returns successful item even if preceded by failing item") { val future1 = Future{throw new IllegalStateException("bad news")} var future2 = Future{"dog"} val futureListOfTrys = Future.allAsTrys(List(future1,future2)) val listOfTrys = Await.result(futureListOfTrys, 10 milli) System.out.println("successItem:" + listOfTrys); assert(listOfTrys(0).failed.get.getMessage.contains("bad news")) assert(listOfTrys(1) == Success("dog")) } test("Future.allAsTrys returns successful item even if followed by failing item") { var future1 = Future{"dog"} val future2 = Future{throw new IllegalStateException("bad news")} val futureListOfTrys = Future.allAsTrys(List(future1,future2)) val listOfTrys = Await.result(futureListOfTrys, 10 milli) System.out.println("successItem:" + listOfTrys); assert(listOfTrys(1).failed.get.getMessage.contains("bad news")) assert(listOfTrys(0) == Success("dog")) } test("Future.allFailedAsTrys returns the failed item and only that item") { var future1 = Future{"dog"} val future2 = Future{throw new IllegalStateException("bad news")} val futureListOfTrys = Future.allFailedAsTrys(List(future1,future2)) val listOfTrys = Await.result(futureListOfTrys, 10 milli) assert(listOfTrys(0).failed.get.getMessage.contains("bad news")) assert(listOfTrys.size == 1) } test("Future.allSucceededAsTrys returns the succeeded item and only that item") { var future1 = Future{"dog"} val future2 = Future{throw new IllegalStateException("bad news")} val futureListOfTrys = Future.allSucceededAsTrys(List(future1,future2)) val listOfTrys = Await.result(futureListOfTrys, 10 milli) assert(listOfTrys(0) == Success("dog")) assert(listOfTrys.size == 1) }
-
==============================
3.난 그냥이 질문을 가로 질러 와서 제공하는 또 다른 해결책을 가지고 :
난 그냥이 질문을 가로 질러 와서 제공하는 또 다른 해결책을 가지고 :
def allSuccessful[A, M[X] <: TraversableOnce[X]](in: M[Future[A]]) (implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = { in.foldLeft(Future.successful(cbf(in))) { (fr, fa) ⇒ (for (r ← fr; a ← fa) yield r += a) fallbackTo fr } map (_.result()) }
여기에서 아이디어는 그 당신이합니다 (대한-이해 구문을 사용하여) 전체에 목록에서 다음 요소를 기다리는 배 내에서 다음 하나가 바로 대체를 실패하면 당신이 이미 가지고있는.
-
==============================
4.스칼라 2.12 적은 코드로 답변에 빌려 준다 Future.transform에 개선이 있습니다.
스칼라 2.12 적은 코드로 답변에 빌려 준다 Future.transform에 개선이 있습니다.
val futures = Seq(Future{1},Future{throw new Exception}) // instead of `map` and `recover`, use `transform` val seq = Future.sequence(futures.map(_.transform(Success(_)))) val successes = seq.map(_.collect{case Success(x)=>x}) successes //res1: Future[Seq[Int]] = Future(Success(List(1))) val failures = seq.map(_.collect{case Failure(x)=>x}) failures //res2: Future[Seq[Throwable]] = Future(Success(List(java.lang.Exception)))
-
==============================
5.당신은 쉽게 옵션을 사용하여 미래의 결과를 래핑 한 다음 목록을 평평하게 할 수 있습니다 :
당신은 쉽게 옵션을 사용하여 미래의 결과를 래핑 한 다음 목록을 평평하게 할 수 있습니다 :
def futureToFutureOption[T](f: Future[T]): Future[Option[T]] = f.map(Some(_)).recover { case e => None } val listOfFutureOptions = listOfFutures.map(futureToFutureOption(_)) val futureListOfOptions = Future.sequence(listOfFutureOptions) val futureListOfSuccesses = futureListOfOptions.flatten
from https://stackoverflow.com/questions/20874186/scala-listfuture-to-futurelist-disregarding-failed-futures by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 언제, 왜 하나는 스칼라에서 실용적 펑터를 사용한다 (0) | 2019.11.08 |
---|---|
[SCALA] 어떻게 미래를위한 미세 조정 스레드 풀을 구성하는 방법? (0) | 2019.11.07 |
[SCALA] 이와 같은 재 시도-수 호출을 구현하는 스칼라 방법은 무엇입니까? (0) | 2019.11.07 |
[SCALA] 함수 프로그래밍 스칼라는지도 왼쪽 접어서 [마감] (0) | 2019.11.07 |
[SCALA] 반복자 대보기 대 스트림 (0) | 2019.11.07 |