2016-08-10 96 views
0

我正在斯卡拉的期貨周圍慢慢地包裹着我的大腦,並有一點點的蛋糕正在嘗試解開。在斯卡拉期貨迷路

具體使用案例是 sangria-graphql + akka。我已經偷了他們的演示代碼,它看起來像這樣

Future.fromTry(Try(
    friendIds map (id => CharacterRepo.humans.find(_.id == id) orElse CharacterRepo.droids.find(_.id == id)))) 

,並加入我自己修改它。他們確實在內存中查找,而我的要求的另一位演員的東西:

Future.fromTry(Try(
    accountIds match { 
     case h :: _ => 
     val f = sender ? TargetedMessage(h) 
     val resp = Await.result(f, timeout.duration).asInstanceOf[TargetedMessage] 
     marshallAccount(resp.body) 

     case _ => throw new Exception("Not found") 
    } 
)) 

這裏的相關部分是我挑的第一個元素在列表中,將其發送到ActorRef,我得到了其他地方,等待結果。這工作。我今天準備這樣做,但是,是不是還得等待結果在這裏,但回到整個事情的Future

Future.fromTry(Try(
    accountIds match { 
     case h :: _ => 
     sender ? TargetedMessage(h) map { 
      case resp:TargetedMessage => marshallAccount(resp.body) 
     } 

     case _ => throw new Exception("Not found") 
    } 
)) 

這是行不通的。當這個被消耗的,而不是Account型(功能marshallAccount返回類型,它的類型作出承諾。如果我理解正確的話,那是因爲,而不是具有Future[Account]返回類型,這有一個類型的Future[Future[Account]]

如何拉平這個

回答

3

您正在尋找在錯誤的API方法Future.fromTry被用來創建一個立即解決的未來,這意味着通話實際上不是異步潛入Future.fromTry實施,這將帶你到:。

def fromTry[T](result: Try[T]): Promise[T] = new impl.Promise.KeptPromise[T](result) 

一個承諾保存基本上是已經發生,所以就像Future.successful這只是用來確保正確的返回類型或類似的東西,它實際上並不是一種方法來做一些異步。

返回類型爲Future[Future[Something]]的原因是因爲您試圖將已經返回未來的東西包裝到另一個未來中。

的詢問模式,即sender ? TargetMessage(h)是一種方法,一些演員和等待的結果,這將返回一個未來。

正確的方式來處理這個:

val future: Future[Account] = accountIds match { 
    case h :: _ => sender ? TargetedMessage(h) map (marshallAccount(_.body) 
    case _ => Future.failed(throw new Exception("Not found")) 
} 

基本上你需要使用Future.failed從異常返回失敗的未來,如果你想保留的返回類型一致。值得回顧this tutorial以瞭解更多關於Futures的信息,以及如何使用它們編寫應用程序邏輯。