1. map, filter
언젠가 값을 가지게 되는 Future에 고차함수를 적용하여 새로운 Future를 얻을 수 있다.
import scala.concurrent.ExecutionContext.Implicits._
val future: Future[Int] = Future { // 2초 후 값 1을 가지게 된다.
TimeUnit.SECONDS.sleep(2L)
1
}
val futureMap: Future[Int] = future.map(_ * 2)
// future가 완료되면 거기에 2를 곱한다
val futureFilter: Future[Int] = futureMap.filter(_ < 1)// futureMap이 완료되면 그 중 1보다 작은 값만을 골라낸다.
2. for
스칼라 어디에든 쓰이는 for문도 사용할 수 있다.
val future: Future[Int] = Future { // 2초 후 값 1을 가지게 된다.
TimeUnit.SECONDS.sleep(2L)
2
}
val result: Future[Int] = for {f <- future
f2 = f * 10 } yield f2
result.onComplete{
case Success(x) => println(x) // 20
}
일반 콜렉션처럼 for문을 이용해 Future 여러개를 묶어 결과를 얻을 수도 있다.
val future: Future[Int] = Future { // 2초 후 값 1을 가지게 된다.
TimeUnit.SECONDS.sleep(2L)
2
}
val future2: Future[Int] = Future { // 1초 후 값 3을 가지게 된다.
TimeUnit.SECONDS.sleep(1L)
3
}
val result: Future[Int] = for {f <- future
f2 <- future2
r = f * f2} yield r
result.onComplete {
case Success(x) => println(x) // 6
}
3. recover
고차함수나 for 모두 새로운 Future를 반환하므로 결국 실제 값을 구하기 위해서는 onComplete 메소드에 부분 함수를 작성하거나 Await.Result 함수를 이용해 블로킹하고 값을 기다려야 한다. Await.Result 함수를 이용하면 Future가 실패해 None 값이 발생할 때 실패 원인에 따른 예외가 발생한다.
futureFilter.onComplete { // 값이 없으므로 None이 출력된다.
case Success(x) => println(x)
case Failure(_) => println("None")
}
/* filter에 해당하는 값이 없어 java.util.NoSuchElementException이 발생한다 */
val result: Int = Await.result(futureFilter, Duration.Inf)
println(result)
None일 때 Exception에 따라 값을 반환해 복구하는 recover 함수를 사용하면 Await.result 함수로도 값을 얻어 낼 수 있다.
val futureFilterRecover: Future[Int] = futureFilter.recover {
case e: java.util.NoSuchElementException => -1
case _ => 0
}
val result: Int = Await.result(futureFilterRecover, Duration.Inf)
println(result) // -1
recover 함수와 비슷하지만 값을 반환하는 대신 새로운 Future를 반환해 작업을 이어가는 recoverWith 함수도 있다.
val future: Future[Int] = Future { // 2초 후 값 1을 가지게 된다.
TimeUnit.SECONDS.sleep(2L)
2
}
val future2: Future[Int] = Future { // 1초 후 값 3을 가지게 된다.
TimeUnit.SECONDS.sleep(1L)
3
}
val futureFiltered: Future[Int] = future.filter(_ > 10) // None (NoSuchElementException)
val futureRecoverWith: Future[Int] = futureFiltered.recoverWith{
case e:NoSuchElementException =>
println("recover")
future2
}
val result = Await.result(futureRecoverWith, Duration.Inf)
println(result)
/*
recover
3
*/
'Scala' 카테고리의 다른 글
Scala 부분 함수(PartialFunction)의 runWith, andThen (0) | 2017.05.10 |
---|---|
Scala, Map Collection의 withDefault, withDefaultValue 메소드 (0) | 2017.05.09 |
Scala의 함수 커링(Currying)과 표현 (0) | 2017.04.14 |
Scala Function Object의 메소드들 (0) | 2017.04.01 |
Java의 CompletableFuture, Scala의 Future와 Promise (0) | 2017.03.28 |