2012-12-12 10 views
10

Jestem nowy w scala i staram się łączyć kilka kontraktów futures w scala 2.10RC3. Model Futures powinien być wykonywany w kolejności. W dokumencie Scala SIP14 zdefiniowano metodę andThen w celu wykonania Futures w porządku sekwencyjnym. Użyłem tej metody, aby połączyć kilka Futures (patrz przykład poniżej). Spodziewałem się, że wydrukuje on 6, ale w rzeczywistości wynikiem jest 0. Co ja tu robię źle? Mam dwa pytania:Kolejno łącz dowolną liczbę kontraktów terminowych w Scala

Po pierwsze, dlaczego jest wynikiem 0. Po drugie, jak mogę połączyć kilka Futures, aby wykonanie drugiego Future nie zostało uruchomione przed zakończeniem pierwszego Future.

val intList = List(1, 2, 3) 

val sumOfIntFuture = intList.foldLeft(Future { 0 }) { 
case (future, i) => future andThen { 
    case Success(result) => result + i 
    case Failure(e) => println(e) 
} 
} 

sumOfIntFuture onSuccess { case x => println(x) } 

Odpowiedz

12

andThen jest dla efektów ubocznych. Pozwala określić pewne działania, które należy wykonać po zakończeniu przyszłości i zanim zostanie użyte do czegoś innego.

Wykorzystanie map:

scala> List(1, 2, 3).foldLeft(Future { 0 }) { 
    | case (future, i) => future map { _ + i } 
    | } onSuccess { case x => println(x) } 
6 
+0

Dzięki! Dokładnie tego potrzebowałem. – Chrisse

+0

+1 To bardzo mi pomogło! – pvorb

2

Lubię ten rodzajowy podejście:

trait FutureImplicits { 

    class SeriallyPimp[T, V](futures: Seq[T]) { 
    def serially(f: T => Future[V])(implicit ec: ExecutionContext): Future[Seq[V]] = { 
     val buf = ListBuffer.empty[V] 
     buf.sizeHint(futures.size) 

     futures.foldLeft(Future.successful(buf)) { (previousFuture, next) => 
     for { 
      previousResults <- previousFuture 
      nextResult <- f(next) 
     } yield previousResults += nextResult 
     } 
    } 
    } 

    implicit def toSeriallyPimp[T, V](xs: Seq[T]): SeriallyPimp[T, V] = 
    new SeriallyPimp(xs) 

} 

Następnie wymieszać w wyżej cechy i używać go tak:

val elems: Seq[Elem] = ??? 
val save: Elem => Future[Result] = ??? 
val f: Future[Seq[Result]] = elems serially save 

Kod ten mógł być ulepszone, aby zachować typ zbierania danych wejściowych. Zobacz artykuł na przykład: this.

Powiązane problemy