2014-03-27 47 views
2

我有一個Future [MyType],它是通過api調用通過線路產生的。如果api調用失敗,因爲發送了錯誤的數據,它只會拋出一個異常(不是很有幫助,但我可以做的沒有什麼)將Future [MyType]轉換爲Future [Option [MyType]]

所以我想用try/catch檢查並返回Future [Option [MyType ]]是這樣的:

def myfunc(name:String):Future[Option[MyType]] = { 
    try { 
    val d:Future[MyType] = apiCall(name) //returns a Future[MyType] 

    ???? Convert d into future(Some(MyType)) 

    } catch { 
    future(None) 
    } 

} 

感謝您抽空看看

回答

4

這真的取決於異常被拋出的確切位置如果apiCall被之前拋出異常它創建的Future,你可以映射Future來包裝該值在Option

try { 
    val d: Future[Option[MyType]] = apiCall(name).map{result => Some(result)} 
} catch { 
    case t: Throwable => Future.successful(None) 
} 

不過,我不認爲這是去是最好的方法,因爲你失去了有效的信息,爲什麼API調用失敗。 Option通常不是一個很好的解決方案,用於指示發生錯誤。我想一個更好的解決辦法是返回一個包含異常的未來:

try { 
    val d:Future[MyType] = apiCall(name) 
} catch { 
    case t: Throwable => Future.failed(t) 
} 

這樣做的原因是什麼代碼,您已經處理未來將不得不應付未來已經內部異常,因此這將讓所有的錯誤處理在一個地方。

如果異常被拋出Future,在try/catch塊,因爲異常不會幫助包裝apiCall不同步引發,所以你可以使用maprecover

val d: Future[Option[MyType]] = apiCall(name).map{Some(_)}.recover{ 
    case t: Throwable => None 
} 
+0

偉大的建議,我不知道錯誤發生在哪裏..我會進一步檢查。感謝您抽出時間 – saintlyRook

+0

不要抓住'Throwable',而是抓住'NonFatal'。另外,如果apiCall返回一個Future,我不會期望它拋出任何東西,而是返回失敗的Future。 – Calavoow

相關問題