2013-11-15 3 views
21

У меня есть вызов, который возвращает будущее. Тем не менее, мне нужно сделать n звонков, поэтому я вернусь к n фьючерсам. Мне интересно, как я хотел бы получить фьючерсы на все решимостью, прежде чем продолжить (без блокировки сервера)Как разрешить список фьючерсов в Scala

Например,

while(counter < numCalls){ 
    val future = call(counter) 
    future.map{ x => 
     //do stuff 
    } 
    counter += 1 
} 

//Now I want to execute code here after ALL the futures are resolved without 
//blocking the server 
+0

Вы можете использовать для ... доходности в сочетании с фьючерсами –

ответ

50

Вы можете использовать Future.sequence(futureList) для преобразования List[Future[X]] в Future[List[X]]. А так как последнее просто просто Future, вы можете дождаться его завершения с помощью Await.ready или аналогичных помощников.

Таким образом, вам нужно будет сохранить список фьючерсов, которые вы создаете. Что-то вроде:

val futures = new ListBuffer[Future[X]] 
while(counter < numCalls) { 
    val future = call(counter) 
    futures += future 
    future.map { x => 
     //do stuff 
    } 
    counter += 1 
} 
val f = Future.sequence(futures.toList) 
Await.ready(f, Duration.Inf) 

, которые можно было бы написать как:

val futures = (1 to numCalls).map(counter => { 
    f = call(counter) 
    f.map(x => ...) 
    f 
}) 
Await.ready(Future.sequence(futures), Duration.Inf) 
+8

За исключением случаев, когда вы вызываете Await.ready, тогда вы будете блокировать - что хорошо для иллюстрации, но вы не должны блокировать ваш производственный код - не если вы действительно можете избежать этого ... и вы почти всегда можете избежать этого. –

+0

Извините, я был в спешке и вставил неправильную линию. Я имел в виду: val f = Future.sequence (futures.toList). Я закончил использовать f.map, чтобы дождаться его решения. – user2816456

6

Чуть более функциональны:

val futures = for { 
    c <- 0 until 10 
    } yield { 
    val f = call(c) 
    f onSuccess { 
     case x => 
     // Do your future stuff with x 
    } 
    f 
    } 
Future.sequence(futures) 
+0

Как это более функционально, что принятый ответ? –

5

я понимаю, что вы хотите сделать что-то после того, как фьючерсы закончены ,например. обратный вызов, без блокировки исходного вызова? Тогда вы должны сделать что-то вроде этого:

val futures = for (...) yield { 
    future { 
    ... 
    } 
} 

val f = Future sequence futures.toList 

f onComplete { 
    case Success(results) => for (result <- results) doSomething(result) 
    case Failure(t) => println("An error has occured: " + t.getMessage) 
} 

http://docs.scala-lang.org/overviews/core/futures.html

Таким образом, вы не блокируете с вызовом ЖДЕТ, но вы все еще ждете всех фьючерсы, чтобы закончить, а затем сделать что-то по всем результатам. Ключевыми аспектами является использование Future.sequence, чтобы объединить много фьючерсов вместе, а затем использовать обратный вызов, чтобы действовать на результат.

Смежные вопросы