2017-12-20 8 views
0

나는 다음과 같은 테스트 코드가 : 그것은 다음과 같은 출력을 생성스칼라 미래 블록 변환?

import scala.concurrent.{Await, Future} 
import scala.concurrent.duration.Duration 
import scala.util.Success 

import scala.concurrent.ExecutionContext.Implicits.global 

object FutureAndThen extends App { 

    val future = Future { 
    println("Started initial Future") 
    10 
    } andThen { case Success(value) => 
    println("Started callback") 
    Thread.sleep(5000) 
    println(s"Finished callback: value = $value") 
    } map { x => 
    println("Chained transformation") 
    x * 2 
    } 

    println(Await.result(future, Duration.Inf)) 

} 

:

Started initial Future 
Started callback 
Finished callback: value = 10 
Chained transformation 
20 

내가 andThen 콜백이 비동기 적으로 수행 될 것으로 기대합니다. 그러나 실제 실행은 다음과 같습니다

  1. 하는
  2. 비동기 콜백
  3. 실행 변환 (map)

는 처음에는이 문제가 ExecutionContext에 있다고 생각 실행 원래의 미래를 실행하는 이 모든 작업을 단일 스레드로 실행하기로 결정했습니다.

implicit val ctx = ExecutionContext.fromExecutor(
    (command: Runnable) => new Thread(command).start() 
) 

을 그리고 결과는 동일 : 그리고이 정의 ExecutionContext 사용하도록 변경. 제가 빠진 것에 대해 조언 해 주시겠습니까?

답변

2

이 동작은 실제로 Future.andThen에 대해 설명되어 있습니다

이 미래의 결과에 사이드 초래 기능을 적용,이 미래의 결과 새로운 미래를 반환합니다.

이 방법은 하나의 에의 콜백은 지정된 순서 실행되는 적용 할 수 있습니다.

mapandThen의 계산이 완료되기 전에 작업을 시작하지 않습니다. 이것이 원하는 것이 아니라면, Futuremap으로 전화해야합니다. 그리고 당신은 대신 andThenonComplete를 사용할 수 있으므로 코드는 다음과 같이 될 것입니다 :

val future = Future { 
    println("Started initial Future") 
    10 
    } 

    future onComplete { case Success(value) => 
    println("Started callback") 
    Thread.sleep(2000) 
    println(s"Finished callback: value = $value") 
    } 

    val f2 = future map { x => 
    println("Chained transformation") 
    x * 2 
    } 

    println(Await.result(f2, Duration.Inf)) 

P.S. AFAIK에는 메서드 체이닝과 함께 사용할 수있는 표준 인 onComplete이 없으므로 코드를 읽음으로써 동작을 예측하기 쉽도록 디자인되었다고 생각합니다. 현재 당신은 간단한 규칙을 사용할 수 있습니다 : 그것이 연결된 경우 - 나중에 실행됩니다.

+0

감사합니다. 이것은 정확하게 내가 어떻게 나의 문제를 해결했는지입니다. –