콘텐츠로 이동

2023 08 31

2023-08-31

Scala Future map, for, recover

참고: https://partnerjun.tistory.com/37

  • map, filter
    • 언젠가 값을 가지는 Future에 대해 고차함수를 적용해 새로운 Future를 얻을 수 있음
      import scala.concurrent.ExecutionContext.Implicits._
      
      val future: Future[Int] = Future {
          TimeUnit.SECONDS.sleep(2L)
          1
      }
      
      val futureMap: Future[Int] = future.map(_ * 2) // future 완료시 거기에 곱하기 2
      val futureFilter: Future[Int] = futureMap.map(_ < 1) // futureMap 완료시 1보다 작은거 골라내기
      
  • for
    • for문도 쓰자요
      import scala.concurrent.ExecutionContext.Implicits._
      
      val future: Future[Int] = Future {
          TimeUnit.SECONDS.sleep(2L)
          1
      }
      
      val result: Future[Int] = for {
          f <- future
          f2 = f * 10
      } yield f2
      
      result.onComplete {
          case Success(x) => println(x)
      }
      
  • recover

    • 고차함수나 for 모두 Future를 반환
    • 실제 값을 구하려면 결국 onComplete 메서드에 부분함수를 작서아거나
    • Await.result를 통해 동기적으로 기다려야 해
    • Future가 실패해 None이 발생하면 예외 처리를 해줘야해

      • onComplete
        futureFilter.onComplete {
            case Success(x) => println(x)
            case Failure(_) => println("None") // NONE에 대해 처리
        }
        
      • Await.result
        val result = Await.result(futureFilter, Duration.Inf) // 기다려도 안나와 java.util.NoSuchElementException
        println(result)
        
    • recover를 사용하면 Await.result 함수로 값을 얻을 수 있음!
      • Future 반환값이 None이면 이걸 뱉어주세요!
        val futureFilterRecover: Future[Int] = futureFilter.recover {
            case e: java.util.NoSuchElementException => -1
            case _ => 0
        }
        
        val result: Int = Await.result(futureFilterRecover, Duration.Inf)
        prinlnt(result) // -1
        
    • recoverWith를 통해 새로운 Future를 반환해 작업을 이어가는 방법도 있음!
      val future: Future[Int] = Future {
          TimeUnit.SECONDS.sleep(2L)
          2
      }
      
      val future2: Future[Int] = Future {
          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) // 3