val metaSeqFutureSeq = appDomains.map(i => getMeta(i))
// Seq[Future[Seq[Meta]]]
val metaSeqSeqFuture = Future.sequence(metaSeqFutureSeq)
// Future[Seq[Seq[Meta]]]
// NOTE :: this future will fail if any of the futures in the sequence fails
val metaSeqFuture = metaSeqSeqFuture.map(seq => seq.flatten)
// Future[Seq[Meta]]
如果您想拒绝唯一失败的未来,但保留成功的未来,那么我们将不得不有点创意,并使用承诺来建立我们的未来。
import java.util.concurrent.locks.ReentrantLock
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.{Future, Promise}
import scala.util.{Failure, Success}
def futureSeqToOptionSeqFuture[T](futureSeq: Seq[Future[T]]): Future[Seq[Option[T]]] = {
val promise = Promise[Seq[Option[T]]]()
var remaining = futureSeq.length
val result = ArrayBuffer[Option[T]]()
result ++ futureSeq.map(_ => None)
val resultLock = new ReentrantLock()
def handleFutureResult(option: Option[T], index: Int): Unit = {
resultLock.lock()
result(index) = option
remaining = remaining - 1
if (remaining == 0) {
promise.success(result)
}
resultLock.unlock()
}
futureSeq.zipWithIndex.foreach({ case (future, index) => future.onComplete({
case Success(t) => handleFutureResult(Some(t), index)
case Failure(ex) => handleFutureResult(None, index)
}) })
promise.future
}
val metaSeqFutureSeq = appDomains.map(i => getMeta(i))
// Seq[Future[Seq[Meta]]]
val metaSeqOptionSeqFuture = futureSeqToOptionSeqFuture(metaSeqFutureSeq)
// Future[Seq[Option[Seq[Meta]]]]
val metaSeqFuture = metaSeqSeqFuture.map(seq => seq.flatten.flatten)
// Future[Seq[Meta]]