수색…


미래 창조

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object FutureDivider {
    def divide(a: Int, b: Int): Future[Int] = Future {
        // Note that this is integer division.
        a / b
    }
}

아주 간단하게 divide 방법의 몫으로 해결하는 미래를 만들어 오버 a b .

성공적인 미래를위한 소비

성공적인 미래를 소비하는 가장 쉬운 방법은 미래의 가치를 얻는 것입니다. map 방법을 사용하는 것입니다. 일부 코드가 "미래 만들기"예제에서 FutureDivider 객체의 divide 메서드를 호출한다고 가정합니다. 코드의 몫 얻는처럼 무엇을해야 오버 a b ?

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
        
        eventualQuotient map {
            quotient => println(quotient)
        }
    }
}

실패한 미래 소비

Future의 계산이 예외를 생성하여 Future가 실패하게 만드는 경우가 있습니다. "Creating a Future"예제에서 호출 코드가 divide 메소드에 550 을 전달하면 어떻게 될까요? 물론 0으로 나눈 후에 ArithmeticException 을 던질 것입니다. 소비 코드에서 어떻게 처리 될까요? 실제로 실패를 처리 할 수있는 몇 가지 방법이 있습니다.

recover 및 패턴 일치로 예외를 처리하십시오.

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
    
        eventualQuotient recover {
            case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

예외가 failed 프로젝션으로 예외를 처리합니다. 여기서 예외는 미래의 값이됩니다.

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
    
        // Note the use of the dot operator to get the failed projection and map it.
        eventualQuotient.failed.map {
            ex => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

미래를 함께 가다.

이전 예제는 성공과 실패 사례를 처리하면서 미래의 개별 기능을 시연했습니다. 그러나 일반적으로 두 기능은 훨씬 더 간결하게 처리됩니다. 다음은 깔끔하고 사실적인 방식으로 작성된 예제입니다.

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
        
        eventualQuotient map {
            quotient => println(s"Quotient: $quotient")
        } recover {
            case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

순차 및 순회 선물

어떤 경우에는 별도의 선물에서 다양한 금액의 가치를 계산해야합니다. List[Future[Int]] 가 있다고 가정하고 대신 List[Int] 를 처리해야합니다. 그런 다음 질문은 List[Future[Int]] 의이 인스턴스를 Future[List[Int]] 입니다. 이를 위해 Future 동반자 객체에 sequence 메소드가 있습니다.

def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.sequence(listOfFuture)

일반적으로 sequenceFG 대한 제한을 가지고 F[G[T]]G[F[T]] 로 변환하는 함수 프로그래밍 세계에서 일반적으로 알려진 연산자입니다.

traverse 라고하는 대체 연산자가 있지만 비슷한 기능을하지만 추가 인수로 함수를 사용합니다. 신원 함수 x => x 를 매개 변수로 사용하면 sequence 연산자처럼 작동합니다.

def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.traverse(listOfFuture)(x => x)

다만, 추가의 인수에 의해, 지정된 listOfFuture 내의 장래의 각 인스턴스를 변경할 수 있습니다. 또한, 첫 번째 인수는 Future 의 목록 일 필요는 없습니다. 따라서 다음과 같이 예제를 변형 할 수 있습니다.

def futureOfList: Future[List[Int]] = Future.traverse(List(1,2,3))(Future(_))

이 경우 List(1,2,3) 는 첫 번째 인수로 직접 전달되고 identity 함수 x => xFuture(_) 로 대체되어 유사하게 각 Int 값을 Future 로 래핑합니다. 이것의 이점은 성능 향상을 위해 중간 List[Future[Int]] 을 생략 할 수 있다는 것입니다.

여러 선물 결합 - 이해를 돕기 위해

for comprehension 은 여러 미래의 성공적인 결과에 의존하는 코드 블록을 실행하는 간결한 방법입니다.

f1, f2, f3 3 개의 Future[String] 각각 one, two, three 의 문자열이 포함됩니다.

val fCombined = 
    for {
        s1 <- f1
        s2 <- f2
        s3 <- f3
    } yield (s"$s1 - $s2 - $s3")

fCombined 는 모든 미래가 성공적으로 완료되면 문자열 one - two - three 포함하는 Future[String] 가됩니다.

여기에는 암시 적 ExectContext가 사용됩니다.

또한 이해는 flatMap 메소드에 대한 구문 론적 설탕 일 뿐이므로 신체 내부의 미래 객체 구성은 미래로 둘러싸인 코드 블록의 동시 실행을 제거하고 순차 코드로 이어지게된다는 것을 명심하십시오. 예를 들어 보자.

val result1 = for {
  first <- Future {
    Thread.sleep(2000)
    System.currentTimeMillis()
  }
  second <- Future {
    Thread.sleep(1000)
    System.currentTimeMillis()
  }
} yield first - second

val fut1 = Future {
  Thread.sleep(2000)
  System.currentTimeMillis()
}
val fut2 = Future {
  Thread.sleep(1000)
  System.currentTimeMillis()
}
val result2 = for {
  first <- fut1
  second <- fut2
} yield first - second

result1 객체로 묶인 값은 항상 음수이고 result2 는 양수입니다.

일반적으로 이해yield 에 대한 자세한 내용은 http://docs.scala-lang.org/tutorials/FAQ/yield.html을 참조 하십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow