2017-10-10 42 views
0

說我有下面的代碼片段轉換列表[未來[INT]]到未來[列表[INT]]失敗的期貨

def testFailure2() = { 
    val f1 = Future.failed(new Exception("ex1")) 
    val f2 = Future.successful(2); 
    val f3 = Future.successful((5)); 
    val f4 = Future.failed(new Exception("ex4")) 
    val l = List(f1, f2, f3, f4) 
    l 
    } 

返回類型是List[Future[Int]]。以正常的方式,我可以做Future.sequence並得到List[Future[Int]]。但在這種情況下,它不會工作,因爲我有一個失敗的未來。所以我想通過忽略失敗的期貨將其轉換爲List [Future [Int]]。我怎麼做?

關於第二個問題,我有類似的話題,我明白filter, collect, partition, etc on a List。在這種情況下,假設我想將filter/partitionlist分成兩個列表 - 一個失敗的期貨 - 在另一個成功完成期貨。

我該怎麼做?

+0

在'Future.sequence'上,無論如何你都必須對結果進行模式匹配,無論結果是「成功(_)」還是「失敗(_)」,在哪裏你可以做任何你想做的事情期貨失敗。 – prayagupd

+0

那麼,Future.sequence是否可以接受一個PF,我只能在成功的未來收集?因爲如果我進行模式匹配,我可能會以Future [Option [Int]]結束,它將更像未來(一些(1)),無等 – curiousengineer

+0

@prayagupd,Future.sequence,需要迭代,我將如何在案件上匹配嗎? – curiousengineer

回答

1

一種方法是首先將所有Future[Int] s轉換爲Future[Option[Int]],它們總是成功(但如果原始未來失敗,將導致None)。然後你可以使用Future.sequence,然後壓平的結果:

def sequenceIgnoringFailures[A](xs: List[Future[A]])(implicit ec: ExecutionContext): Future[List[A]] = { 
    val opts = xs.map(_.map(Some(_)).fallbackTo(Future(None))) 
    Future.sequence(opts).map(_.flatten) 
} 
+0

這是一個很好的片段。非常感謝。但是我可以不使用收集已經成功的期貨進行PF嗎?我無法考慮如何以及如果可能的話 – curiousengineer

+0

列表的收集方法將不得不立即執行,而您將不知道未來是否會成功到期。 –

1

對方回答是正確的:你應該使用一個Future [列表[X],其中X是失敗與成功之間的區分的東西。它可以是一個選項,任一個,嘗試或任何你想要的。

好像你被這種困擾,我想這是因爲你願意找這樣的:

  • 做所有這些期貨並行的過程中,忽略了那些失敗

而你給

  • 做所有這些期貨,等待一切完成,並丟棄基於結果

但實際上,沒有特殊的方式表達「忽略失敗的人」。因爲你對它感興趣,所以有些事情必須承認每一個未來的結果,否則一開始就沒有意義。無論如何,這件事必須等待所有的未來。正因爲如此,「你現在可以不理我了」的標誌的確是Option爲None,或者是Left,或者是Trying Failure。 afaik沒有一個特定的標誌來表示「這個結果被丟棄」,我不認爲scala會需要它。

所以,不要害怕,併爲未來[列表[X]],因爲它實際上表達了你想要的! :-)

+0

我得到答案。您的回答也幫助我確信,除了您的建議外,沒有別的辦法。我發現了另一個類似的答案,包含在Try中。我正在努力將其包裝在「左/右」中。一旦我映射List,我就會得到一個'Future [Int]''。但是我無法對它進行匹配以填寫「左/右」。我正在嘗試的語法不能編譯。我怎麼做? – curiousengineer

+0

終於知道了吧 'val again = l.map {fut => fut.map(x => Right(x))。recover {case f => Left(f)}} – curiousengineer

+0

看起來很完美:) – C4stor